Lesson 6 / 27
Error Responses: Problem Details
Return consistent, machine-readable errors that help the caller fix the problem.
Errors are part of the contract
Clients must handle failures, so give every error the same shape. A standard is Problem Details for HTTP APIs (RFC 9457, which replaces RFC 7807), media type application/problem+json, with members type (a URI identifying the error kind), title, status, detail and optional extensions such as an errors list for field-level validation. Make messages actionable (say what to change), use stable machine-readable type or code values that clients can switch on, include a request ID for support, and never leak internals such as stack traces, SQL or file paths.
A problem+json response, run
I ran this against a small real HTTP API built with only the Python standard library (full code in the case study). Requesting a missing item returns 404 with content type application/problem+json and the standard members.
# uses srv, base and call() from the runnable demo in the case study
s, h, b = call("GET", "/v2/items/99"); print(s, h["Content-Type"], b)
Output:
404 application/problem+json {'type': 'about:blank', 'title': 'Not Found', 'status': 404, 'detail': 'Item 99 does not exist.'}A validation error with field details
The errors extension lists each invalid field so a UI can highlight it. (Shape from the demo API, shown as JSON.)
{
"type": "https://api.example.com/problems/validation",
"title": "Validation failed",
"status": 422,
"detail": "amount must be positive.",
"errors": [{"field": "amount", "message": "must be > 0"}],
"request_id": "req_8f3a21"
}Quick check: Why give every error the same JSON shape?
- JSON requires it
- It hides the status code
- It makes responses longer by design
- Clients can handle all failures with one parser and logic
Answer
Clients can handle all failures with one parser and logic — Predictable errors reduce client code and make failures easy to log and search.