Consistent API Errors with Problem Details (RFC 9457)
Every API needs an error format, and many invent their own. Problem Details (RFC 9457, which replaced RFC 7807) is a standard JSON shape for HTTP API errors that clients and tools already understand.
The format
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
{
"type": "https://api.example.com/problems/insufficient-credit",
"title": "Not enough credit",
"status": 403,
"detail": "Your balance is ₹120, but this costs ₹500.",
"instance": "/orders/abc123",
"balance": 120
}
type- a URI that identifies the kind of problem (ideally a docs page). Clients switch on this.title- short, human-readable summary that doesn't change between occurrences.status- the HTTP status code.detail- explanation of this specific occurrence.instance- which request or resource it relates to.- Extra members (like
balance) are allowed for problem-specific data.
Validation errors
{
"type": "https://api.example.com/problems/validation",
"title": "Your request has invalid fields",
"status": 422,
"errors": [
{ "pointer": "/email", "detail": "must be a valid email address" },
{ "pointer": "/items/0/quantity", "detail": "must be at least 1" }
]
}
JSON Pointers tell front-ends exactly which field to highlight.
Express helper
function problem(res, status, type, title, extra = {}) {
res.status(status).type('application/problem+json').json({
type: `https://api.example.com/problems/${type}`,
title,
status,
...extra,
});
}
problem(res, 404, 'not-found', 'Order not found', { instance: req.originalUrl });
Rules
- Never put stack traces or SQL in
detail. - Keep
typevalues stable; clients depend on them. - Include a request ID (in a header or extension member) so support can find the logs.
Was this article helpful?
Comments
No comments yet. Have a question or a tip? Be the first to share it.