Claude API errors
A practical Claude API error reference covering response formats, HTTP status codes, likely causes, and safe retry rules.
Updated: July 25, 2026.
Error shape
Claude API Tech can return errors in Anthropic- or OpenAI-compatible format. In both formats, the error object contains the error type and explanation, while request_id in the Anthropic format helps identify a specific request during debugging or a support inquiry.
Anthropic Error Format
JSON
{
"type": "error",
"error": {
"type": "rate_limit_error",
"message": "Rate limit exceeded"
},
"request_id": "req_..."
}OpenAI Error Format
JSON
{
"error": {
"message": "Invalid model ID",
"type": "invalid_request_error",
"code": "invalid_model"
}
}Common HTTP errors
| HTTP | Type | Meaning |
|---|---|---|
| 400 | invalid_request_error | Invalid JSON, a required field is missing, a parameter is unsupported by the model, or the messages structure is invalid. |
| 401 | authentication_error | The API key is missing, malformed, revoked, or expired. |
| 403 | permission_error | The key is recognized but cannot access the model, workspace, or another resource. |
| 404 | not_found_error | The endpoint, model, or resource ID does not exist. |
| 409 | conflict_error | The request conflicts with the resource's current state, such as a concurrent modification. |
| 413 | request_too_large | The HTTP body is too large. Anthropic limits Messages and Token Counting requests to 32 MB. |
| 429 | rate_limit_error | A request, input-token, or output-token limit was exceeded; a sudden traffic increase can also trigger an acceleration limit. |
| 500 | api_error | An unexpected internal API error occurred. |
| 504 | timeout_error | The API did not finish processing the request in time. |
| 529 | overloaded_error | The API is temporarily overloaded by traffic. |
Safe retry rules
Retry only transient errors and increase the pause between attempts.
- 1Retry requests on 429, 500, 504, and 529. Other 4xx responses require fixing the request first.
- 2Always honor retry-after when the server returns this header.
- 3Without retry-after, use exponential backoff with random jitter and a maximum delay.
- 4Cap the number of attempts, retain request_id, and do not blindly retry non-idempotent operations.
const RETRYABLE = new Set([429, 500, 504, 529]); async function requestWithRetry(url: string, init: RequestInit) { for (let attempt = 0; attempt < 5; attempt++) { const response = await fetch(url, init); if (response.ok) return response; if (!RETRYABLE.has(response.status) || attempt === 4) { throw new Error(`Request failed: ${response.status}`); } const retryAfter = response.headers.get("retry-after"); const retryAfterSeconds = Number(retryAfter); const backoff = Math.min(500 * 2 ** attempt, 10_000); const delay = retryAfter !== null && Number.isFinite(retryAfterSeconds) ? retryAfterSeconds * 1000 : backoff + Math.random() * 250; await new Promise((resolve) => setTimeout(resolve, delay)); }}