Guides
Errors
Every error the gateway returns is an OpenAI-compatible envelope with a stable code. The messages are written so an agent can self-correct from the code and message alone.
The error envelope
Every failure on /v1/chat/completions, /v1/responses, and /v1/models returns the same shape, so existing OpenAI error handling keeps working:
{
"error": {
"message": "The requested model alias is not granted to this identity.",
"type": "permission_error",
"code": "model_not_granted",
"param": null
}
}Branch on code, not the message text; the message is human-readable and may change, the code is stable.
Stable codes
| code | HTTP | Meaning | How to recover |
|---|---|---|---|
| invalid_json | 400 | The request body is not valid JSON. | Fix the request body. |
| invalid_request | 400 | The request is malformed. | Read the message, fix the request, and resend. |
| invalid_parameter | 400 | A field is invalid; param names it. | Correct that field and resend. |
| unsupported_capability | 400 | The model cannot do what you asked (a tool, a modality, reasoning). | Pick a capable model; check supported_params and modalities in /api/models. |
| continuation_unavailable | 400 | previous_response_id is unknown or expired on this worker. | Resend the full conversation instead of continuing. |
| invalid_key | 401 | The key is missing, malformed, expired, or revoked. | Fix the Authorization header. |
| model_not_granted | 403 | Your organization cannot call this slug. | Use a slug returned by GET /v1/models. |
| idempotency_conflict | 409 | The same Idempotency-Key was reused with a different body. | Use a fresh Idempotency-Key. |
| idempotency_replay_unavailable | 409 / 500 | The original keyed result is gone after a restart. | Resend with a new Idempotency-Key. |
| insufficient_quota | 429 | A spend limit or your credit balance is exhausted; the message says which (a daily org cap, a per-model cap, or credits). | Add credits or raise limits at /credits (platform-funded lane only). |
| unavailable_route | 429 / 503 | Throttled, or no healthy route right now. | Retry with backoff. |
| gateway_overloaded | 429 | The bounded replay window is full. | Retry with backoff. |
| request_cancelled | 499 | The client disconnected before completion. | Reissue the request if you still want the result. |
| all_routes_failed | 502 | Every provider in the waterfall failed. | Retry; if you are on BYOK, check your provider key. |
| provider_output_too_large | 502 | Provider output exceeded the gateway response limit. | Lower max output tokens. |
| gateway_draining | 503 | This instance is draining and is not taking new requests. | Retry; the request lands on another instance. |
| deadline_exceeded | 504 | The request ran past the gateway deadline. | Shorten the work or retry. |
| internal_error | 500 | An unexpected failure. | Retry with backoff. |
Any unknown /v1 path returns 404 with code=not_found. The gateway serves exactly /v1/models, /v1/chat/completions, and /v1/responses.
What to retry
- Retry
429(throttled or overloaded),502,503, and504with exponential backoff. - Do not blindly retry
400,401,403, or409. Fix the request first; the same call fails the same way. insufficient_quotais not transient: it clears when you add credits or raise a limit, not on retry.
Delivery is at-least-once: an ambiguous network failure that you retry can dispatch and bill the underlying provider twice. Pass an
Idempotency-Key header so an exact retry replays the original result instead of running again.See also
The API reference documents each endpoint, and /llms.txt carries this same error table for agents.