Python SDK Exception Types at a Glance
A dense reference for every exception class the anthropic Python SDK raises, and whether each one is safe to retry.
Search across all documentation pages
A dense reference for every exception class the anthropic Python SDK raises, and whether each one is safe to retry.
except chain - most specific first.| Exception | HTTP status | Retry-safe? | Typical cause |
|---|---|---|---|
BadRequestError | 400 | No | Malformed request, invalid parameter value |
AuthenticationError | 401 | No | Missing or invalid API key |
PermissionDeniedError | 403 | No | API key lacks access to the requested model or feature |
NotFoundError | 404 | No | Invalid model ID or endpoint |
UnprocessableEntityError | 422 | No | Request is well-formed JSON but semantically invalid |
RateLimitError | 429 | Yes (already auto-retried) | Exceeded requests-per-minute, tokens-per-minute, or tokens-per-day |
InternalServerError | 5xx | Yes (already auto-retried) | Transient Anthropic service issue |
APIConnectionError | (no response) | Yes (already auto-retried) | DNS failure, connection refused, network interruption before any response |
APIStatusError | any non-2xx | Depends - base class | Catch-all for any HTTP error not matched by a more specific subclass above |
APIError | (any) | Depends - base class | Root of the whole exception hierarchy; broadest possible catch |
import anthropic
try:
message = client.messages.create(
model="claude-sonnet-5",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello"}],
)
except anthropic.NotFoundError:
# Bad model ID or endpoint - fix the request, do not retry
...
except anthropic.RateLimitError:
# Exhausted the SDK's own retries; back off longer or reduce request rate
...
except anthropic.APIStatusError as e:
# Any other non-2xx HTTP response
print(e.status_code, e.message)
except anthropic.APIConnectionError:
# Network failure before any response was received
...APIConnectionError is a sibling of APIStatusError in Python (not a subclass), so it needs its own except clause; it will not be caught by an except anthropic.APIStatusError branch.
| Failure | Auto-retried by default? | Your code needs to... |
|---|---|---|
APIConnectionError (network failure) | Yes, up to max_retries (default 2) | Handle only if retries are exhausted |
429 (RateLimitError) | Yes, honoring retry-after | Handle only if retries are exhausted; consider a longer backoff |
5xx (InternalServerError) | Yes | Handle only if retries are exhausted |
408, 409 | Yes | Handle only if retries are exhausted |
400, 401, 403, 404, 422 | No | Fix the request or credentials; retrying unchanged fails again |
| Exception | Recommended strategy |
|---|---|
RateLimitError (after retries exhausted) | Back off significantly longer than the SDK's default retry window, or shed load; consider a token-bucket rate limiter client-side |
APIConnectionError (after retries exhausted) | Surface a "service unreachable" state to the user; check your own network/DNS before assuming Anthropic is down |
InternalServerError (after retries exhausted) | Check status.anthropic.com; if persistent, treat as an outage rather than a code bug |
AuthenticationError | Never retry; verify ANTHROPIC_API_KEY is set and valid, then fail loudly - a silent retry loop against a bad key just wastes time |
BadRequestError | Never retry unchanged; log the request payload (redacting secrets) and fix the malformed field |
PermissionDeniedError | Never retry; the API key needs different permissions or a different model access grant |
NotFoundError | Never retry; almost always a typo'd model ID - check against the current model catalog |
.type for Finer-Grained ClassificationEvery APIStatusError subclass exposes a .type string matching the API's own error taxonomy, useful when a single HTTP status covers more than one underlying cause:
except anthropic.APIStatusError as e:
if e.type == "rate_limit_error":
...
elif e.type == "overloaded_error":
...
elif e.type == "invalid_request_error":
...Not for the common case.
The SDK already retries 429s automatically up to max_retries times with backoff; write your own handling only for what happens after retries are exhausted.
Because it represents a failure that happened before any HTTP response was received (a network error), whereas APIStatusError and its subclasses represent a response that came back with a non-2xx status. They need separate except clauses.
APIError is the root of the entire hierarchy, including APIConnectionError. APIStatusError covers only responses that actually reached you with an HTTP status code. Catching APIStatusError specifically excludes connection-level failures.
No.
A bad or missing API key does not become valid by retrying; fix the credential and fail fast instead of looping.
The request was valid JSON with the right shape, but the API rejected its contents for a semantic reason - for example, a budget_tokens value that doesn't satisfy the API's constraints for that field.
RateLimitError maps to HTTP 429 specifically, while overloaded_error (a 529) is typically caught as APIStatusError - check e.type == "overloaded_error" inside that branch to distinguish it.
Writing a single broad except anthropic.APIError: (or catching plain Exception) that treats every failure identically, losing the distinction between retryable and non-retryable errors. Catch the most specific class you care about first.
Yes.
The exception hierarchy is identical between Anthropic() and AsyncAnthropic() - only the calling convention (await) differs.
It's the most common cause, but any invalid endpoint path (unlikely if you're only using the SDK's own methods) would also produce a 404. Double-check the exact model ID string against the current catalog first.
At minimum, e.status_code, e.message, and e.type. Avoid logging the full request body unredacted if it could contain sensitive user content.
max_retries actually retries before these exceptions surfaceStack versions: Written against the Claude model lineup current as of ~June 2026 - Claude Fable 5, Claude Opus 4.8, Claude Sonnet 5 (the default), and Claude Haiku 4.5 - and the official
anthropicPython SDK (latest 0.x release). Model names, SDK versions, and pricing move quickly - verify current specifics at platform.claude.com/docs before relying on them.
Reviewed by Chris St. John·Last updated Jul 19, 2026