Skip to main content

Errors

The error envelope, HTTP status codes, machine-readable error codes, errors inside streams, and how to report a failure.

On this page

The error envelope

Most errors come in one JSON envelope with the matching HTTP status. The Anthropic-compatible endpoints use Anthropic’s envelope, and a few responses from the edge of the platform carry no envelope at all: see Responses without the envelope.

Error response
{
  "error": {
    "status": 403,
    "message": "Access denied",
    "code": "AUTHZ_2001",
    "detail": "API key missing required scope: llm:access or llm:chat",
    "request_id": "6c5d0c9e-0000-4000-8000-000000000000"
  }
}
Field Meaning
status The HTTP status code.
message A short, display-safe summary for the status.
code A machine-readable code. Branch on status first, then code.
detail What went wrong with this request. Do not parse it; wording can change.
errors On 422 only: one entry per invalid field, with field, message, type and, for numeric bounds, constraints.
request_id The request’s correlation id.

Every response, success or failure, carries an X-Request-ID header. An unexpected server error also carries X-Error-ID. Include both when you contact support.

Status codes

Status Code When
400 VALIDATION_4002 The request is malformed or fails a server-side check.
401 AUTH_1001, or another AUTH_10xx code No valid credential: missing, malformed, expired or revoked.
402 see below No spendable credit, or the spend cap is reached.
403 AUTHZ_2001, or another AUTHZ_20xx code The credential is valid but lacks a scope or permission, or the account is suspended or inactive.
404 RESOURCE_3001 The resource does not exist or belongs to someone else.
409 RESOURCE_3003 A replay of an idempotent request, or another conflict.
413 none The request body is over 10 MiB. No envelope; see below.
422 VALIDATION_4001 The body or parameters fail schema validation.
428 see below A step-up is required, for example a recent sign-in to create a key.
429 RATE_5001 A per-key LLM API limit was exceeded, or the limiter is unavailable. The per-user limits answer without the envelope; see below.
500 INTERNAL_9002 An unexpected error. The response also carries X-Error-ID, and the body never contains internal details.
500 INTERNAL_9001 An internal error the server handled and reported deliberately.
502 EXTERNAL_6004 An upstream engine returned an unusable response.
503 INTERNAL_9003 A dependency is temporarily unavailable.
504 EXTERNAL_6005 An upstream engine timed out.

Stored responses, batches and files that belong to another user or organization return 404, not 403, so a response never confirms that someone else’s object exists.

Responses without the envelope

These responses are produced before a request reaches an endpoint, or on a path that keeps a structured body, so they do not use the envelope:

Status Body When
400 {"detail": "Malformed Content-Length header."} The Content-Length header is not a number.
413 {"detail": "Request too large"} The body is over 10 MiB. The wording can differ slightly.
429 {"detail": "...", "retry_after": 60} A per-user limit on the Platform API, embeddings or rerank. Also sent with Retry-After: 60. See Rate limits.
503 {"error": {"message": "...", "type": "transient_timeout", "code": "...", "recovery_exhausted": true}} A non-streaming chat completion finished without an answer. code is empty_completion or reasoning_budget_exhausted. There is no status or request_id field; read X-Request-ID from the headers.

A robust client branches on the HTTP status first, reads error.code when the body has one, and otherwise falls back to detail. Retry the 503 above with backoff.

Errors inside a stream

Once a streaming response has started, its HTTP status is already 200. A failure after that point arrives as one final event, followed by the end marker:

In-band stream error
data: {"error": {"message": "The AI model is temporarily unavailable. Please try again shortly.", "type": "transient_timeout", "code": "stream_interrupted"}}

data: [DONE]

Treat any data: event with an error object as a failed request. Codes you may see include context_length_exceeded, provider_rate_limited, stream_interrupted, incomplete_stream, empty_completion and budget_exhausted.

Anthropic-compatible errors

The Messages API returns Anthropic’s envelope with the same HTTP status, so Anthropic SDKs raise their usual exceptions:

Anthropic error
{ "type": "error", "error": { "type": "rate_limit_error", "message": "Rate limit exceeded: <limit> requests/minute" } }

Retry-After and X-Request-ID are passed through, and x-should-retry: false is set when retrying cannot help (402, 409).

Retrying

Retry? Statuses
Yes, with backoff 429, 502, 503, 504, and stream errors with transient_timeout
After fixing the request 400, 413, 422
After fixing credentials or permissions 401, 403, 428
After adding credit or raising the cap 402
Not as-is 409 (send a new Idempotency-Key if you mean to run it again)

Honour Retry-After when present. Use exponential backoff with jitter, cap the number of attempts, and send an Idempotency-Key so a retry after a lost response cannot run twice.

Search documentation

Type to search guides, the API reference, the CLI and the console guide.

    Enter open↑ ↓ moveEsc close