Error responses
Parse the common Router error envelope and recover according to status and code.
Router returns errors as JSON before a stream starts.
{ "error": { "message": "No provider is available for this model", "type": "server_error", "code": "no_priced_provider_available" }}Use the HTTP status for broad control flow, the stable code for a specific product message, and message for a human-readable explanation.
Common API errors
| Status | Code or category | Recovery |
|---|---|---|
| 400 | Invalid body, unknown model, output_limit, prompt_too_large, or unsupported input | Correct the request before trying again. |
| 400 | context_length_exceeded | The messages exceed the edition’s context window in tokens. Shorten them before trying again. |
| 400 | stream_required | A non-streaming request asked for more than 512 output tokens or sent more than about 24 KB of message text. Set stream to true, or shorten the request. |
| 400 | idempotency_key_required | Send a caller-generated UUID in Idempotency-Key. |
| 401 | auth_no_token or invalid_api_key | Supply a valid bearer key or rotate an expired or revoked key. |
| 402 | insufficient_credits | Add shared credits or lower the request maximum. |
| 402 | budget_exhausted | Router's UTC monthly spending cap is reached. |
| 402 | charge_limit_exceeded | This request's worst-case charge exceeds its authorized maximum. |
| 403 | account_disabled | Resolve account access; repeated requests will not help. |
| 409 | provider_price_changed | Review the current selected offer price and explicitly accept its new revision in a new logical request. |
| 409 | provider_offer_unavailable | Select another published eligible offer, or explicitly omit the selection for Auto. |
| 409 | idempotency_conflict | This UUID was already used with a different body, credential, or X-Max-Charge-Credits value. Resend the original terms, or use a new UUID for a new request. |
| 409 | request_in_progress | Router is still admitting the earlier request with this UUID. Check its credit receipt, then retry with the same UUID and body if needed. |
| 409 | request_already_exists | A streaming request with this UUID already exists. Streams are not replayed; check its credit receipt. |
| 429 | Request-rate or concurrency limit | Respect Retry-After and reduce parallel work. |
| 503 | no_priced_provider_available | No eligible paid provider can accept this model now. |
| 503 | no_provider_for_length | No online provider serves a request this long right now. Shorten the messages or the answer limit; an immediate retry will not help, so respect Retry-After (60 seconds). |
| 503 | selected_provider_unavailable | The selected computer is busy or offline; Router does not silently fall back. |
| 503 | self_provider_only | Select a provider owned by another account. |
| 503 | request_capacity | Router’s bounded active-request capacity is full; retry later. |
| 503 | credit_admission_unavailable or settlement_pending | Keep the request UUID and check its credit receipt; never start a new paid request just to recover. |
| 503 | slippage_tolerance_exceeded | No charge or reservation. Review error.minimum_slippage_tolerance and submit new terms with a new request UUID if appropriate. |
| 503 | pricing_pending | Pricing research is running; no charge or reservation. Retry unchanged terms after Retry-After. |
| 503 | suggested_price_unavailable | Baseline storage or generation is unavailable; no charge or reservation. Retry later or choose another model. |
| 503 | Generation or dependency failure | Show a temporary failure and retry the same logical request ID only when safe. |
Error messages can evolve. Branch application behavior on status and code rather than matching the English message.
Streaming errors
After streaming headers are sent, a generation failure arrives as an SSE data event with an error object and the request's request_id. The HTTP status may already be 200.
data: {"error":{"message":"Generation or settlement interrupted","type":"server_error","code":"provider_timeout"},"request_id":"$REQUEST_ID"}
data: [DONE]An error event is terminal for that generation. A [DONE] marker may still follow; it does not turn the reply into a success. Do not treat already-received content as a complete answer, and check the request's credit receipt before retrying. Codes vary by failure.
When streaming, an input longer than the model's context window arrives this way too, as "type":"invalid_request_error","code":"context_length_exceeded" with no answer text. Retrying the same messages fails again: shorten them first. No tokens were generated, so the request's reservation is released.
Retry headers
429 and temporary capacity responses can include Retry-After. Interpret an integer value as seconds, add jitter before retrying, and keep the total number of attempts bounded.
See retries, timeouts, and cancellation for an application strategy.