Error handling
Handle API errors before they reach users.
Build predictable recovery paths for authentication failures, usage rules, rate limits, validation errors, and dependency failures.
Last updated: July 6, 2026. Examples use safe placeholders and do not include real API keys or customer prompts.
Client-side rule
Log enough context to debug the failure, but never log raw API keys, secrets, payment data, or full customer prompts.
Failure map
Start with the class of failure.
Most integration problems fall into one of five buckets. Classify the response first, then choose the next action.
Authentication errors
Confirm the Authorization header, key format, active status, expiration, IP allowlist, and required endpoint scope before retrying.
Quota exceeded
Quota errors mean the request would cross a package limit for requests, tokens, or images. Reduce usage, wait for reset, or change package capacity.
Validation failures
Invalid JSON, missing fields, unsupported values, and malformed payloads should be fixed client-side before the same request is sent again.
Dependency failures
An internal dependency or network path can fail after your request is accepted. Treat transient 5xx failures with bounded retries and keep support context redacted.
Support escalation
Escalate repeat failures with endpoint, timestamp, status, error code, environment, masked key prefix, and any request ID or provider trace ID when routing is enabled.
Response shape
Parse the OpenAI-compatible error object.
Check the HTTP status first, then branch on error.code for the recovery path.
{
"error": {
"message": "Missing or invalid API key.",
"type": "authentication_error",
"code": "invalid_api_key"
}
}| Status | Codes | Common cause | Next action |
|---|---|---|---|
| 400 | invalid_json, invalid_payload | The request body is not valid JSON or does not match the endpoint schema. | Fix the payload and resend only after validation passes. |
| 401 | invalid_api_key | The API key is missing, malformed, or not recognized. | Check the Bearer token, environment variable, and key prefix. |
| 402 | subscription_inactive, subscription_unavailable | The subscription attached to the key cannot access the API. | Review billing status before sending more customer-facing traffic. |
| 403 | inactive_api_key, expired_api_key, ip_not_allowed, insufficient_scope | The key is known but blocked by status, expiration, IP policy, or scope. | Rotate or update the key, then retry with the required scope. |
| 429 | request_quota_exceeded, token_quota_exceeded, image_quota_exceeded, quota_exceeded | The request would exceed package quota. | Reduce request size, wait for the quota period, or choose a larger package. |
| 429 | rate_limit_exceeded | The client is sending requests faster than the local rate limit allows. | Respect Retry-After when present and use exponential backoff. |
| 501 | streaming_not_enabled | The requested feature is recognized but not enabled for the endpoint. | Disable the unsupported option or contact support if the feature is required. |
| 5xx | Check response body | An internal dependency or network path failed. | Retry idempotent work with backoff, then escalate repeat failures with context. |
Retry guidance
Retry only the failures that can recover.
Retries help with temporary pressure or dependency failures. They make validation, permissions, and billing problems noisier if nothing changes.
Retry with backoff
429 rate_limit_exceeded, 408, 500, 502, 503, 504
Use bounded exponential backoff with jitter. Respect Retry-After when the response includes it.
Do not retry unchanged
400, 401, 402, 403, 501
Fix the request, key, billing state, permission, or feature flag before trying the same call again.
Retry after capacity changes
429 quota codes
Quota errors usually need smaller payloads, delayed work, or a package change rather than immediate retries.
async function callWithBackoff(runRequest) {
for (let attempt = 0; attempt < 3; attempt += 1) {
const response = await runRequest();
if (response.ok) {
return response;
}
const retryable = [408, 429, 500, 502, 503, 504].includes(response.status);
if (!retryable) {
return response;
}
const retryAfter = Number(response.headers.get("retry-after") ?? 0);
const delayMs = retryAfter > 0 ? retryAfter * 1000 : 500 * 2 ** attempt;
await new Promise((resolve) => setTimeout(resolve, delayMs));
}
return runRequest();
}Implementation notes
Keep retry attempts bounded so one user action cannot create a traffic spike.
Add jitter in production clients that send concurrent traffic.
Surface a useful user message after the final retry instead of hiding the failure.
Capture redacted diagnostics before the retry loop exits.
Escalation
Send support the context they can act on.
A good escalation packet shortens triage without exposing secrets, prompts, or customer data.
Contact supportFAQ
Error handling questions.
What error shape should my client expect?
The /v1 API returns an OpenAI-compatible JSON error object with error.message, error.type, and error.code. Validation errors can also include field-level details.
Should I retry every 429 response?
No. Retry short rate_limit_exceeded responses using Retry-After when present. For quota codes, reduce usage, wait for reset, or choose a package with more capacity.
What should I send to support?
Share endpoint, method, timestamp, status, error code, masked key prefix, environment, and any request ID. Include external trace IDs only when support asks for them. Do not send raw API keys, secrets, or customer prompts.
Free tools
Debug errors with free tools
Look up error codes, decode 429 responses, simulate retries, and plan rate-limit monitoring.
Error Code Lookup
Search unlimitedcodex error codes, HTTP statuses, retry guidance, and recovery actions.
429 Decoder
Paste a 429 response body and headers to classify rate-limit vs quota pressure and see retry guidance.
Retry Simulator
Tune backoff and retry settings to see simulated outcomes and copy a retry handler snippet.
Rate Limit Planner
Plan backoff settings and quota monitoring checklist from expected RPS and team size.