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

# Errors

> Error catalog and how to handle them

All error responses follow the **standard OpenAI format**:

```json theme={null}
{
  "error": {
    "message": "Insufficient balance. Recharge at https://app.geekhub.mx/dashboard/billing.",
    "type": "insufficient_balance",
    "code": "insufficient_balance",
    "request_id": "req_aacb6a7d478c2fdea077ca09"
  }
}
```

The `request_id` is end-to-end traceable. If you report a bug, include it — we can find your request in the logs.

## Error catalog

| HTTP  | `code`                  | What to do                                                                                         |
| ----- | ----------------------- | -------------------------------------------------------------------------------------------------- |
| `400` | `invalid_request_error` | Review the body (Zod tells you the exact field in `message`)                                       |
| `401` | `missing_api_key`       | Send `Authorization: Bearer ghub_sk_...` header                                                    |
| `401` | `invalid_api_key`       | Verify the key is correct and not revoked                                                          |
| `401` | `key_revoked`           | Generate a new one at `/dashboard/keys`                                                            |
| `402` | `insufficient_balance`  | Top up at `/dashboard/billing/recharge`                                                            |
| `404` | `model_not_found`       | Call `GET /v1/models` to see the valid catalog                                                     |
| `429` | `rate_limit_exceeded`   | Retry with exponential backoff (coming soon)                                                       |
| `500` | `internal_error`        | Retry. If it persists, open a ticket with `request_id`                                             |
| `502` | `provider_unavailable`  | The provider (Anthropic/OpenAI/etc) is down or your prompt isn't acceptable. Retry or switch model |

## Provider-specific errors

If `code` is `provider_unavailable`, the `message` comes from the original provider as-is. Common examples:

```
404 The model 'gpt-4o' does not exist            ← Your account doesn't have access
content_filter triggered                          ← Anthropic / OpenAI blocked the prompt
rate limit reached for model xxx                 ← Temporary provider overload
```

## Recommended retry

```python theme={null}
import time
from openai import OpenAI

def call_with_retry(client, model, messages, max_retries=3):
    for attempt in range(max_retries):
        try:
            return client.chat.completions.create(
                model=model,
                messages=messages,
            )
        except Exception as e:
            if attempt == max_retries - 1:
                raise
            # Exponential backoff: 1s, 2s, 4s
            time.sleep(2 ** attempt)
```

## Streaming errors

If you request `stream: true` and something fails **after** the stream starts, you receive a final SSE message with the error shape:

```
data: {"error":{"message":"...","type":"provider_unavailable","code":"provider_unavailable","request_id":"req_xxx"}}
```

Your parser should check whether the line contains `error` in addition to `[DONE]`.
