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

# Error codes

> The HTTP statuses, error structure and handling tips OpenPAI returns

On error, OpenPAI returns a standard HTTP status code plus a JSON error body.
The error structure is fully compatible with OpenAI's, so it plugs seamlessly into existing SDK error handling.

## Error response structure

```json theme={null}
{
  "error": {
    "message": "Incorrect API key provided.",
    "type": "invalid_request_error",
    "param": null,
    "code": "invalid_api_key"
  }
}
```

| Field     | Meaning                                                                                                                  |
| --------- | ------------------------------------------------------------------------------------------------------------------------ |
| `message` | A human-readable error description, fine to show to developers                                                           |
| `type`    | Error category: `invalid_request_error` / `authentication_error` / `billing_error` / `rate_limit_error` / `server_error` |
| `param`   | The name of the offending field (if applicable)                                                                          |
| `code`    | A machine-recognizable error code                                                                                        |

## Common error codes

### 400 invalid\_request

| code                      | Meaning                                                 |
| ------------------------- | ------------------------------------------------------- |
| `invalid_request_error`   | Malformed request body / missing required field         |
| `invalid_model`           | Model ID doesn't exist or isn't in the token allowlist  |
| `context_length_exceeded` | Input + output tokens exceed the model's context window |
| `unsupported_modality`    | The model doesn't support image / audio / video input   |

### 401 authentication

| code               | Meaning                                        |
| ------------------ | ---------------------------------------------- |
| `invalid_api_key`  | API key doesn't exist / deleted / wrong format |
| `expired_api_key`  | The token has expired                          |
| `disabled_api_key` | The token has been disabled                    |

### 403 forbidden

| code                 | Meaning                                   |
| -------------------- | ----------------------------------------- |
| `insufficient_quota` | Account or token quota exhausted          |
| `ip_not_allowed`     | The source IP isn't in the allowlist      |
| `model_not_allowed`  | The token lacks permission for this model |

### 404 not\_found

| code                 | Meaning                                        |
| -------------------- | ---------------------------------------------- |
| `model_not_found`    | The model doesn't exist (retired / misspelled) |
| `resource_not_found` | The resource (task, file) doesn't exist        |

### 429 rate\_limit

| code                        | Meaning                               |
| --------------------------- | ------------------------------------- |
| `rate_limit_exceeded`       | RPM / TPM rate limit hit              |
| `concurrent_limit_exceeded` | Concurrency exceeds the group ceiling |
| `upstream_rate_limited`     | The upstream vendor returned a 429    |

The 429 response includes a `Retry-After` header (seconds); use exponential-backoff retries.

### 5xx server\_error

| code                   | Meaning                                      |
| ---------------------- | -------------------------------------------- |
| `server_error`         | Internal gateway error, usually auto-retried |
| `upstream_unavailable` | All upstream channels are unavailable        |
| `upstream_timeout`     | Upstream timed out                           |
| `bad_gateway`          | The upstream returned an invalid response    |

5xx errors are **not billed** (if the upstream already generated tokens, they're settled by actual usage).

## Errors during streaming

If a streaming response errors midway, it sends an error event as SSE and then closes the connection:

```
data: {"error":{"message":"Upstream timeout","type":"server_error","code":"upstream_timeout"}}

data: [DONE]
```

The client should watch for the `error` field in the SSE data, not just the HTTP status code.

## Retry guidance

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

client = OpenAI(api_key="sk-...", base_url="https://openp.ai/v1")

def call_with_retry(**kwargs):
    delay = 1
    for attempt in range(5):
        try:
            return client.chat.completions.create(**kwargs)
        except openai.RateLimitError:
            time.sleep(delay)
            delay = min(delay * 2, 30)
        except openai.APIError as e:
            if e.status_code >= 500:
                time.sleep(delay)
                delay = min(delay * 2, 30)
            else:
                raise
    raise RuntimeError("max retries exceeded")
```

## Reporting issues

When you get an error you can't make sense of:

1. Copy the `X-OpenPAI-Request-Id` from the response headers.
2. Search for that ID in Console → Logs to see metadata like the model, token usage and error code.
3. If you still can't pin it down, record the Request ID and reproduction steps for later investigation.
