Errors
The AI API returns standard HTTP status codes. Most error responses share a single JSON envelope; the exceptions are listed under other response shapes.
Standard error envelope
Section titled “Standard error envelope”{ "error": { "message": "model not found: openai/does-not-exist", "type": "not_found_error", "code": 404, "request_id": "9f4dc8fb8841f0b0cc67612b6ef54fb7" }}| Field | Type | Notes |
|---|---|---|
error.message |
string | Human-readable description. |
error.type |
string | Machine-readable category (e.g. not_found_error). See status codes. |
error.code |
integer | Matches the HTTP status code. |
error.request_id |
string | Identifier for this request, also returned in the X-Request-Id response header. Quote it when you contact support. |
Authentication and permission failures use this envelope too — see
Authentication
for what to do about each. The WWW-Authenticate header is set on
401 responses:
WWW-Authenticate: Bearer realm="ai-services"Status codes
Section titled “Status codes”| Status | error.type |
Meaning | Retry? |
|---|---|---|---|
400 |
invalid_request_error |
Invalid request body or parameters. | No — fix the request. |
401 |
authentication_error |
Missing, invalid, or revoked API key. | No — check the key. |
402 |
insufficient_credits |
No credits remaining on the account. | No — contact support to add credits. |
403 |
permission_error |
Valid key, but it lacks the required scope. | No — change the key’s permissions. |
404 |
not_found_error |
Unknown model identifier, or the resource doesn’t exist. | No — fix the request. |
429 |
rate_limit_error |
Rate limit exceeded. See rate limits. | Yes — back off with jitter. |
500 |
internal_error |
Unexpected gateway error. | Yes — retry with backoff. |
502 |
upstream_error |
The model provider returned an error. | Yes — retry with backoff. |
503 |
upstream_error or credits_unavailable |
The model provider, or the credit balance check, is temporarily unavailable. | Yes — retry with backoff. |
504 |
timeout_error |
The model provider timed out. | Yes — retry with backoff. |
Some operations can also return 409 or 422; the
API reference lists the status codes for
each operation.
Model provider errors
Section titled “Model provider errors”The gateway doesn’t pass a model provider’s error body through. It returns the standard envelope with a status based on the provider’s:
| Provider status | Gateway response |
|---|---|
400 |
400 — “the upstream provider rejected the request” |
404 |
404 — “the requested model or resource was not found” |
429 |
429 — “rate limited by the upstream provider” |
408 or 504 |
504 — “the upstream provider timed out” |
| Anything else | 502 — “upstream provider error” |
A provider 429 means the model is busy, not that you exceeded your
own limit, but handle it the same way: back off and retry.
Other response shapes
Section titled “Other response shapes”A few responses don’t use the standard envelope. Check the status code first and parse the body defensively.
-
429from the load balancer. When you exceed a rate limit, the body is a short HTML page, not JSON. -
Unknown path or method. A path that doesn’t exist returns a plain-text
404 page not found, and an unsupported method returns a plain-text405 Method Not Allowed. -
/v1/messages. The Anthropic-compatible endpoint returns errors in Anthropic’s format, so Anthropic SDKs can parse them. There is nocodefield; read the status from the response:{"type": "error","error": {"type": "not_found_error","message": "model not found: anthropic/does-not-exist","request_id": "fc0a809a263761c3e07ee97440121445"}}
Streaming errors
Section titled “Streaming errors”Streaming responses ("stream": true on chat completions) that fail
before the first byte return a normal error response. Once the stream
has started, the status is already 200, so a failure arrives inside
the stream instead. If the gateway loses the model provider’s stream,
it sends an error event followed by [DONE]:
data: {"error":{"message":"stream relay error","type":"server_error"}}
data: [DONE]This frame doesn’t follow the standard envelope: its type is
server_error, and it carries no code or request_id.
Treat a chunk with an error field as a failed response, even though
[DONE] follows it. If the connection closes without data: [DONE],
the stream was cut off. Both are recoverable failures — retry the
request. Stream a chat completion
shows code that handles both.
If the client disconnects mid-stream, the gateway stops relaying and records the usage consumed up to that point.