> ## Documentation Index
> Fetch the complete documentation index at: https://docs.metabind.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Handling

> Understanding error responses from the Metabind API

The Metabind API uses standard HTTP status codes and returns detailed error objects to help you understand and handle errors effectively.

## Error Response Format

All error responses follow a consistent format:

```json theme={null}
{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human readable message",
    "details": {
      "field": "Additional error context"
    }
  }
}
```

| Field     | Type   | Description                      |
| --------- | ------ | -------------------------------- |
| `code`    | string | Machine-readable error code      |
| `message` | string | Human-readable error description |
| `details` | object | Additional context (optional)    |

## HTTP Status Codes

### Success Codes

| Code             | Description                             |
| ---------------- | --------------------------------------- |
| `200 OK`         | Request succeeded                       |
| `201 Created`    | Resource created successfully           |
| `204 No Content` | Request succeeded with no response body |

### Client Error Codes

| Code                       | Description                              |
| -------------------------- | ---------------------------------------- |
| `400 Bad Request`          | Invalid request syntax or parameters     |
| `401 Unauthorized`         | Missing or invalid authentication        |
| `403 Forbidden`            | Valid auth but insufficient permissions  |
| `404 Not Found`            | Resource does not exist                  |
| `409 Conflict`             | Resource conflict (e.g., duplicate name) |
| `422 Unprocessable Entity` | Validation failed                        |
| `429 Too Many Requests`    | Rate limit exceeded                      |

### Server Error Codes

| Code                        | Description                     |
| --------------------------- | ------------------------------- |
| `500 Internal Server Error` | Unexpected server error         |
| `502 Bad Gateway`           | Upstream service error          |
| `503 Service Unavailable`   | Service temporarily unavailable |

## Common Error Codes

### Validation Errors

```json theme={null}
{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "Request validation failed",
    "details": {
      "name": "Name is required",
      "email": "Invalid email format"
    }
  }
}
```

### Resource Not Found

```json theme={null}
{
  "error": {
    "code": "NOT_FOUND",
    "message": "Content not found",
    "details": {
      "resourceType": "content",
      "resourceId": "cont123"
    }
  }
}
```

### Duplicate Resource

```json theme={null}
{
  "error": {
    "code": "ALREADY_EXISTS",
    "message": "A component with this name already exists",
    "details": {
      "field": "name",
      "value": "ProductCard"
    }
  }
}
```

### Invalid Status Transition

```json theme={null}
{
  "error": {
    "code": "INVALID_STATUS_TRANSITION",
    "message": "Cannot publish deleted content",
    "details": {
      "currentStatus": "deleted",
      "requestedStatus": "published"
    }
  }
}
```

### Component In Use

```json theme={null}
{
  "error": {
    "code": "COMPONENT_IN_USE_BY_DRAFT",
    "message": "Cannot delete component used by draft content"
  }
}
```

### Circular Dependency

```json theme={null}
{
  "error": {
    "code": "CIRCULAR_DEPENDENCY",
    "message": "Package dependency cycle detected",
    "details": {
      "cycle": ["projectA@1.0.0", "projectB@1.0.0", "projectA@1.0.0"]
    }
  }
}
```

## Rate Limiting

When you exceed the rate limit, you'll receive a `429 Too Many Requests` response:

```json theme={null}
{
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "message": "Too many requests",
    "details": {
      "retryAfter": 60
    }
  }
}
```

The `retryAfter` field indicates the number of seconds to wait before retrying.

### Rate Limit Headers

Rate limit information is included in response headers:

| Header                  | Description                          |
| ----------------------- | ------------------------------------ |
| `X-RateLimit-Limit`     | Maximum requests per window          |
| `X-RateLimit-Remaining` | Remaining requests in current window |
| `X-RateLimit-Reset`     | Unix timestamp when the limit resets |

## Handling Errors

### JavaScript Example

```javascript theme={null}
async function fetchContent(id) {
  try {
    const response = await fetch(
      `https://api.metabind.ai/app/v1/organizations/org123/projects/proj456/content/${id}`,
      {
        headers: {
          'Authorization': 'Bearer YOUR_JWT',
          'Content-Type': 'application/json'
        }
      }
    );

    if (!response.ok) {
      const error = await response.json();

      switch (response.status) {
        case 401:
          throw new Error('Authentication required');
        case 403:
          throw new Error('Permission denied');
        case 404:
          throw new Error(`Content ${id} not found`);
        case 429:
          const retryAfter = error.error.details?.retryAfter || 60;
          throw new Error(`Rate limited. Retry after ${retryAfter}s`);
        default:
          throw new Error(error.error.message);
      }
    }

    return await response.json();
  } catch (error) {
    console.error('API Error:', error.message);
    throw error;
  }
}
```

### Retry Strategy

For transient errors (5xx, 429), implement exponential backoff:

```javascript theme={null}
async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fetch(url, options);

      if (response.status === 429 || response.status >= 500) {
        const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
        await new Promise(resolve => setTimeout(resolve, delay));
        continue;
      }

      return response;
    } catch (error) {
      if (attempt === maxRetries - 1) throw error;
    }
  }
}
```

## Best Practices

<AccordionGroup>
  <Accordion title="Always check the error code">
    Use the `code` field for programmatic error handling, not the `message` field which may change.
  </Accordion>

  <Accordion title="Log error details">
    The `details` object contains valuable debugging information. Log it for troubleshooting.
  </Accordion>

  <Accordion title="Handle rate limits gracefully">
    Implement exponential backoff and respect the `retryAfter` value.
  </Accordion>

  <Accordion title="Validate before sending">
    Validate data client-side before making API calls to avoid unnecessary 400/422 errors.
  </Accordion>
</AccordionGroup>
