Handle API Errors
Real network calls fail, and a production LLM client lives or dies by how it reacts. The single most useful instinct is to split failures into two buckets: ones worth retrying (a transient hiccup that will probably clear) and ones you must fix in the request (a bug in your call that no amount of retrying will help). The HTTP status code tells you which bucket you are in.
In real code you catch the SDK's typed exceptions, which each carry a .status_code (illustrative only -> we do not call the network):
import anthropic
try:
resp = client.messages.create(model="claude-sonnet-4-6", max_tokens=1024,
messages=history)
except anthropic.RateLimitError: # HTTP 429 -> back off and retry
...
except anthropic.APIStatusError as e: # any other 4xx/5xx, has e.status_code
if should_retry(e.status_code):
... # retry with backoff
else:
raise # 400/401/403/404 -> a bug in YOUR request, surface itThe buckets, by status code:
- Retry ->
429(rate limited),500(server error),503(unavailable),529(overloaded). These are transient: wait, then try again. - Fix the request ->
400(bad request),401(bad API key),403(forbidden),404(wrong model or path). Retrying a malformed call just burns quota. - Unknown -> anything else (including a success like
200): do not assume it is safe to retry.
You are building two small functions. classify_error(status) returns the bucket name: "retry", "fix-request", or "unknown". should_retry(status) returns the boolean -> True exactly when the status is in the retry set, else False.
This lesson decides whether to retry; the wait between attempts is its own skill. The production-patterns module covers exponential backoff (double the delay each attempt: 1s, 2s, 4s ...), and on top of that you ADD jitter -> a small random amount of extra wait -> so that a fleet of clients knocked back at the same instant do not all retry on the same beat and stampede the server again (the "thundering herd"). Build it so the status table yields several different answers (429 -> retry, 400 -> fix-request, 200 -> unknown), which means no single constant can pass.
Write classify_error(status) returning "retry" for {429, 500, 503, 529}, "fix-request" for {400, 401, 403, 404}, and "unknown" for anything else. Write should_retry(status) returning the boolean True exactly when status is in the retry set, else False.
This lesson is locked
Lessons open one at a time. Finish the previous lesson to unlock this one.