Skip to main content
Errors use the OpenAI-compatible shape — an error object with message, type, code, and param. The same message and code are mirrored at the top level, alongside a request_id for support. Some errors add extra top-level fields (retry_after on a 429; scope, limit, and spent on a spend-limit 402; maximum_hold_usd on max_cost_exceeded):
That’s the zero-balance case, checked before the body is read. If you have a balance but it can’t cover this request’s pre-authorization hold, chat returns the same code with a dynamic message: "Insufficient credits for the maximum token hold of $0.012345." The hold is a reserve sized from your input plus the output ceiling; a completed request settles to actual usage.

Error reference

400 — fix the request

401 / 403 — fix the credential

402 — add credits or raise a limit

404, 409, 410, 413, 429

5xx — retry

Streams can also fail after the HTTP status has been sent. In that case the last data frame is an error object — partial_stream (some output was delivered; only delivered tokens are billed) or stream_error (nothing was delivered; not charged). See Streaming.

Error handling code

The official SDKs retry 429 and 500/502/503/504 when the request is safe to replay, honor Retry-After, and generate an Idempotency-Key for billed requests so a retry can only replay. A 409 request_in_flight is retried only when the request carried an idempotency key; 408 is never retried. The clients expose typed errors:

Common mistakes

Monitor before a 402

Query client.balance() on a schedule and register a signed balance.low webhook for the prepaid $5 and $1 thresholds. Project spend limits also emit budget.alert at 50%, 80%, and 100%. See Observability for the complete operating loop and signature verification.

Quick debug