# Common errors

https://omnimodel.me/docs/errors

When a call fails, check the HTTP status and error code, then use the table below. Error messages follow the `Accept-Language` header (`zh-CN` or `en-US`).

## Error formats

| API | Format |
| --- | --- |
| OpenAI-compatible `/v1/*` | `{"error": {"message", "type", "code", "request_id"}}` |
| Anthropic-compatible | `{"type": "error", "error": {"type", "message"}}`, with no machine-readable code |
| Gemini-compatible | `{"error": {"code", "message", "status"}}` |
| Platform API `/api/v1/*`, media tasks | `{"code", "message", "request_id", "details"}` |

Include the `request_id` when contacting support.

## Common error codes

| Code | HTTP | Cause | What to do |
| --- | --- | --- | --- |
| `auth.invalid_key` | 401 | Wrong, paused, expired or revoked key, or the key was put in the URL | Check the key and the request header |
| `auth.forbidden` | 403 | The model is not in the key's allowed models | Update the key's allowed models |
| `key.ip_denied` | 403 | Source IP is not on the key's allowlist | Update the IP allowlist |
| `key.spend_limit` | 402 | The key hit its daily or monthly spend limit (`billing.key_limit_exceeded` in the OpenAI format) | Raise the limit or wait for the period to roll over |
| `billing.insufficient_credit` | 402 | Balance cannot cover the call's estimated cost | Top up |
| `billing.in_arrears` | 403 | The account is in arrears | Top up to clear the arrears |
| `rate.limited` | 429 | Request rate limit exceeded | Back off and retry |
| `concurrency.exceeded` | 429 | Too many requests in progress | Wait for running requests to finish |
| `model.unavailable` | 404 | Unknown, in maintenance, retired, or lacking the capability this endpoint needs | Check the model ID and [capabilities](/docs/capabilities?lang=en) |
| `routing.not_applied` | 409 | The model has no usable supply route right now | Retry later or use another model |
| `upstream.unavailable` | 503 | The upstream failed or timed out | Retry later; failed calls are free |
| `account.restricted` | 403 | API calls are paused for the account | Check notifications or open a ticket |
| `content.prohibited.*` | 403 | The request hit a content rule | Change the content, or appeal via the link in `details` |

## Retrying

- 429 and 503 are retryable; use exponential backoff with a retry cap.
- 401, 402, 403 and 404 will not succeed on retry; fix the cause first.
- Non-streaming requests time out after 120 seconds in total, so use streaming for long outputs.

## FAQ

### How should I retry a 429?

Both rate.limited and concurrency.exceeded are retryable. Use exponential backoff with a retry cap and reduce concurrent requests.

### Am I charged for upstream.unavailable?

No. Calls that fail or time out upstream count as failed and are free; retry later.

### Why is there no error code in the Anthropic format?

Anthropic error bodies carry only a type and message. Use the OpenAI-compatible API if you need machine-readable codes.

