OpenAI-compatible endpoints normally return a JSON error object:
{
"error": {
"message": "Invalid API key",
"type": "invalid_request_error",
"code": "invalid_api_key"
}
}
Claude, Gemini, and asynchronous task endpoints may preserve protocol-specific error fields. Classify errors by HTTP status first, then record the complete response body and any request ID in the response headers. Do not depend on one fixed type or code value.
Common status codes
| Status | Meaning | What to do |
|---|---|---|
400 | Invalid parameters, model, or request shape | Fix the request; do not replay it unchanged |
401 | Missing, invalid, or disabled key | Check the authentication header and token status |
403 | Token or group lacks permission | Check model scope and account permissions |
404 | Endpoint, model, or task not found | Verify the URL, model ID, or task ID |
409 | Request state conflict | Follow the error detail and inspect task or idempotency state |
429 | Rate, concurrency, or quota limit | Back off exponentially and reduce concurrency |
500 | Internal gateway error | Keep the request ID and retry after a short delay |
502 / 503 / 504 | Temporary upstream failure or timeout | Retry safely replayable requests with backoff |
Retry policy
- Retry transient
429,500,502,503, and504responses only; honorRetry-Afterwhen present. - Use exponential backoff with jitter, for example 1, 2, 4, and 8 seconds, with both an attempt limit and an overall timeout.
- A non-streaming read-like request is usually safe to retry. Once a streaming response has emitted content, retrying creates a new generation.
- Do not blindly replay billable or asynchronous image and video requests. Query the task ID, or add application-level idempotency.
- Do not retry most
400,401,403, or404errors until the request or permissions change.
Troubleshooting record
Keep the timestamp, endpoint, model ID, HTTP status, request ID, and a redacted response body. Never paste a complete API key into logs or support tickets.