Troubleshooting: Claude API Errors¶
As of 2026-10-24, based on the current Claude API reference and the official errors page. Concepts: 06 · Errors, rate limits and retries.
Read the error before you fix it¶
Every error response has the same shape:
{
"type": "error",
"error": {"type": "invalid_request_error", "message": "messages: roles must alternate between \"user\" and \"assistant\""},
"request_id": "req_..."
}
error.typetells you the category;error.messageusually tells you the exact field.- Log the
request_id(also in therequest-idresponse header). Support needs it. - In the Python SDK, catch typed exceptions from most to least specific:
import logging
import anthropic
log = logging.getLogger(__name__)
client = anthropic.Anthropic()
def queue_for_later() -> None:
"""Placeholder for your own retry queue (for example a job queue with delayed retry)."""
try:
resp = client.messages.create(model="claude-opus-5-5", max_tokens=1024,
messages=[{"role": "user", "content": "ping"}])
except anthropic.BadRequestError as e: # 400: fix the request, do not retry
log.error("bad request %s: %s", e.request_id, e.message)
except anthropic.AuthenticationError: # 401
raise
except anthropic.NotFoundError as e: # 404: usually the model ID
log.error("not found: %s", e.message)
except anthropic.RateLimitError: # 429: SDK already retried; back off further or queue
queue_for_later()
except anthropic.APIStatusError as e: # other HTTP errors, including 5xx and 529
log.error("status %s", e.status_code)
except anthropic.APIConnectionError: # network, DNS, TLS, timeout
log.error("connection problem")
Quick table¶
| HTTP | error.type |
Retry? | Most common cause |
|---|---|---|---|
| 400 | invalid_request_error |
No | Malformed body or a parameter the model rejects |
| 401 | authentication_error |
No | Missing, wrong or revoked key |
| 402 | billing_error |
No | Billing or payment problem |
| 403 | permission_error |
No | Credential, workspace or region not allowed |
| 404 | not_found_error |
No | Model ID typo or model not available to your organisation |
| 413 | request_too_large |
No | Body over the size limit |
| 429 | rate_limit_error |
Yes, after retry-after |
Requests or tokens per minute exceeded |
| 500 | api_error |
Yes, with backoff | Transient server problem |
| 529 | overloaded_error |
Yes, with backoff | Temporary capacity pressure |
400 invalid_request_error¶
Symptom: the call fails immediately with a 400 and a message naming a field.
Likely causes (current models):
| Message mentions | Cause | Fix |
|---|---|---|
temperature, top_p, top_k |
Sampling parameters are rejected on current models | Remove them; control output with instructions, examples and effort |
budget_tokens, thinking.type.enabled / disabled |
Legacy thinking configuration | Use thinking={"type": "adaptive"} or omit it; set output_config={"effort": ...} |
Final message is assistant / prefill |
Assistant prefill is not supported | End with a user message; use structured outputs for format |
tool_choice any / tool not supported |
Forced tool use is rejected on Opus 5.5, Sonnet 5.5, Fable 5.1 and Mythos 5.1 | tool_choice: auto plus an explicit instruction; strict: true on the tool; or structured outputs |
roles must alternate / first message |
Message order | First message user; alternate roles; merge consecutive same-role messages |
max_tokens |
Above the model's output limit | Lower it, or stream for large values |
tool_use ids were found without tool_result |
Tool loop bug | Return a tool_result for every tool_use id in the next user message |
anthropic-beta unexpected value |
Unknown or not-enabled beta | Fix the header spelling; check your organisation has access |
Invalid signature in thinking block |
Earlier turns or thinking blocks were edited | Keep history append-only; pass thinking blocks back unchanged |
Schema / input_schema |
Invalid JSON Schema in a tool or output format | Validate the schema; with strict: true include required and additionalProperties: false |
citations with output_config.format |
The two features cannot be combined | Choose one per request |
Diagnosis: read error.message; diff the failing body against a known-good minimal request; check whether code
copied from an older tutorial still sends retired parameters.
Fix: correct the body. Never retry a 400 unchanged. Add a request-validation step (this repository's mock client does this offline; see labs troubleshooting).
401 authentication_error¶
Symptom: every call fails with 401.
Likely causes: ANTHROPIC_API_KEY unset in the process that runs the code; a typo or stray whitespace; a revoked
key; both ANTHROPIC_API_KEY and ANTHROPIC_AUTH_TOKEN set; an OAuth token sent as x-api-key instead of
Authorization: Bearer.
Diagnosis:
python -c "import os; k=os.environ.get('ANTHROPIC_API_KEY',''); print('set' if k else 'missing', len(k))"
(Print presence and length only, never the key.) Check which shell, container or CI job actually runs the code.
Fix: set the variable in the right environment (a secrets manager in CI, .env loaded locally, never committed);
unset the conflicting variable; rotate the key if it may have leaked.
402 billing_error and 403 permission_error¶
Symptom: valid key, but calls are refused.
Likely causes: billing not set up or credits exhausted (402); the key's workspace is not allowed the operation, a region or access requirement applies, or an organisation policy blocks the model (403).
Diagnosis: check the Console's billing and workspace pages; read the message, which often says what to do.
Fix: resolve billing; use a key from the correct workspace; ask your administrator for access.
404 not_found_error¶
Symptom: not_found_error with a message starting model: ....
Likely causes: typo (claude-opus-5.5 instead of claude-opus-5-5); an invented date suffix; a retired model; a
model your organisation cannot use (the API returns 404 rather than revealing it exists); wrong endpoint path.
Diagnosis: client.models.list() shows exactly which IDs you can use.
Fix: use the exact ID from the models overview; keep model IDs in configuration, not scattered through code.
413 request_too_large¶
Symptom: large requests fail before processing.
Likely causes: big base64 PDFs or images, very long conversation history, many documents in one call.
Diagnosis: measure the serialised body size; count tokens with count_tokens.
Fix: upload once with the Files API and reference file_id; resize images; split documents; retrieve only relevant
chunks (RAG); compact or trim history.
429 rate_limit_error¶
Symptom: intermittent 429s under load, often in bursts.
Likely causes: requests per minute, input tokens per minute or output tokens per minute exceeded for your tier; many workers starting at once; retry storms; a separate limit for a premium mode.
Diagnosis: read the retry-after and anthropic-ratelimit-* / x-ratelimit-* headers; plot request and token
rates; check whether retries multiply traffic.
Fix:
- Honour
retry-after; exponential backoff with jitter; cap concurrency with a queue or semaphore. - Cut tokens: prompt caching (cached reads count differently towards limits; see the rate limits page), shorter outputs, retrieval instead of whole documents.
- Move non-urgent work to Message Batches.
- Request a higher tier if sustained demand justifies it. See 15 · Rate limits and capacity.
500 api_error and 529 overloaded_error¶
Symptom: occasional server errors, more frequent during peaks.
Likely causes: transient service issues or capacity pressure.
Diagnosis: check status.anthropic.com; confirm the error rate across many requests, not one.
Fix: the SDK retries twice by default (max_retries); add your own backoff with jitter and an overall deadline;
degrade gracefully (queue, cached answer, smaller model for non-critical paths); alert when error rates cross a
threshold. Make retried operations idempotent so a retry never duplicates a side effect.
Timeouts and streaming errors¶
| Symptom | Likely cause | Diagnosis | Fix |
|---|---|---|---|
| Client times out on long answers | Non-streaming request with a large max_tokens |
Compare elapsed time to SDK timeout | Stream (messages.stream) and use get_final_message() |
Stream stops with an error event |
Server-side error mid-stream (for example overload) | Inspect the event payload | Retry the request; design the UI to handle partial output |
| Wall-clock far longer than the timeout | Timeouts are retried | Count attempts in logs | Set timeout and max_retries deliberately per route |
pause_turn stop reason |
Long server-tool turn paused | Check stop_reason |
Send the response back unchanged to continue |
Errors that are not HTTP errors¶
| Symptom | Cause | Fix |
|---|---|---|
HTTP 200 but stop_reason: "refusal" |
A safety classifier declined | Read stop_details; see prompts and outputs |
| HTTP 200 but JSON fails to parse | stop_reason: "max_tokens" truncated output |
Check stop_reason first; raise max_tokens or use structured outputs |
| Web search returns an error object | Server tool errors arrive inside the result block | Branch on the result content type before indexing |
Prevention checklist¶
- Model IDs and limits in config; startup check with
models.retrieve. - Typed exception handling with retry only for 429, 5xx and connection errors.
-
request_id, model,stop_reasonandusagelogged for every call. - Concurrency limits and backoff with jitter.
- Contract tests that send your real request shapes to a mock validator in CI.