Claude Skills
CollectionsCompareWorkflowsNominate
Sign inSign up
© 2026 Curated Agent Skills·Learn more about Agent Skills
Back to repository

defensive-api-handling

verified

Safely handles API responses to prevent crashes from malformed JSON, HTML error pages, or unexpected response types. Use any time calling API endpoints.

View on GitHub

Marketplace

alphaagent-team

the-answerai/alphaagent-team

Plugin

aai-core

workflow

Repository

the-answerai/alphaagent-team

plugins/aai-core/skills/defensive-api-handling/SKILL.md

Last Verified

February 1, 2026

Install Skill

Select agents to install to:

Scope:
npx add-skill https://github.com/the-answerai/alphaagent-team/blob/main/plugins/aai-core/skills/defensive-api-handling/SKILL.md -a claude-code --skill defensive-api-handling

Installation paths:

Claude
.claude/skills/defensive-api-handling/
Powered by add-skill CLI

Instructions

# Defensive API Handling

**Purpose**: Safely handle API responses to prevent crashes

**When to Use**: Any time you call an API endpoint (in tests or production code)

---

## Never Assume API Returns JSON

APIs can return:
- JSON (expected)
- HTML error pages
- Empty responses
- Malformed JSON
- Non-200 status codes

**Your code must handle ALL of these safely.**

---

## Pattern 1: Safe JSON Parsing

```typescript
async function safeJsonParse(response: Response): Promise<unknown | null> {
  // 1. Check status code
  if (!response.ok) {
    console.warn(`API returned ${response.status} ${response.statusText}`);
    return null;
  }

  // 2. Check content type
  const contentType = response.headers.get('content-type');
  if (!contentType?.includes('application/json')) {
    console.warn(`Expected JSON, got ${contentType}`);
    const text = await response.text();
    console.warn(`Response body: ${text.slice(0, 200)}`);
    return null;
  }

  // 3. Try to parse
  try {
    return await response.json();
  } catch (error) {
    console.warn('Failed to parse JSON:', error.message);
    return null;
  }
}
```

---

## Pattern 2: Fetch with Timeout

```typescript
async function fetchWithTimeout(
  url: string,
  options: RequestInit = {},
  timeoutMs: number = 10000
): Promise<Response> {
  const controller = new AbortController();
  const timeout = setTimeout(() => controller.abort(), timeoutMs);

  try {
    const response = await fetch(url, {
      ...options,
      signal: controller.signal
    });
    return response;
  } finally {
    clearTimeout(timeout);
  }
}
```

---

## Pattern 3: Retry Logic

```typescript
async function fetchWithRetry(
  url: string,
  options: RequestInit = {},
  maxRetries: number = 3,
  delayMs: number = 1000
): Promise<Response | null> {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetchWithTimeout(url, options);

      // Retry on 5xx errors
      if (response.status >= 500 && att

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
4590 chars