Error Handling¶
The client turns API failures into a small hierarchy of typed exceptions, so you can catch exactly the condition you care about instead of parsing status codes by hand.
The error envelope¶
WiseFood error responses follow a consistent shape:
{
"success": false,
"error": {
"title": "NotFoundError",
"detail": "Article with URN urn:article:hello not found.",
"code": "resource/not_found"
},
"help": "https://data.wisefood.example/api/v1/articles/hello"
}
The client inspects every response (raise_for_api_error) and, on failure, raises an
appropriate APIError subclass — even for 2xx responses that carry success: false.
The APIError base¶
All client exceptions inherit from wisefood.exceptions.APIError, which exposes:
Attribute |
Meaning |
|---|---|
|
HTTP status code. |
|
Server error code, e.g. |
|
Server error title, e.g. |
|
Human-readable message (validation details are flattened in). |
|
Nested/structured errors (e.g. field validation). |
|
Any additional server-provided fields. |
|
The top-level |
|
The raw parsed JSON of the response. |
|
|
Exception mapping¶
The client first maps the server code; if there’s no match it falls back to the HTTP
status code.
Server |
HTTP status |
Exception |
|---|---|---|
|
400 |
|
|
401 |
|
|
403 |
|
|
404 |
|
|
405 |
|
|
409 |
|
|
422 |
|
|
429 |
|
|
500 |
|
|
502 |
|
|
503 |
|
|
504 |
|
All of these are importable from wisefood.exceptions.
Catching errors¶
from wisefood.exceptions import NotFoundError, RateLimitError, AuthorizationError
try:
article = client.articles["does-not-exist"]
except NotFoundError as e:
print(e.code, "-", e.detail)
print("More info:", e.help_url)
except AuthorizationError:
print("You don't have access to this resource.")
except RateLimitError as e:
if e.retryable:
... # back off and retry
Tip
The client already retries transient failures (429, 500, 502, 503, 504) with
backoff at the HTTP layer. The RateLimitError/5xx exceptions surface only when those
automatic retries are exhausted — so a manual retry loop is rarely needed, but
retryable is there if you want one.
Validation errors¶
For 422 responses, FastAPI-style validation details are flattened into a readable
detail string while the structured form remains available on .errors:
from wisefood.exceptions import DataError
try:
client.articles.create() # missing required fields
except DataError as e:
print(e.detail) # e.g. "body.title: field required"
print(e.errors) # the structured list