Routes and errors
Standardize API errors
Return one useful problem-details shape for validation, missing resources, conflicts, and unexpected failures.
8 minute lesson
Clients should not need a different parser for every error. Standard fields make failures machine-readable and still understandable to a person.
Use the problem-details fields type, title, status, detail, and optional application-specific extensions. Do not expose stack traces, SQL, secrets, or internal file paths. Log unexpected detail on the server with a request identifier.
{
"type": "https://example.com/problems/invalid-book",
"title": "Book input is invalid",
"status": 422,
"errors": { "title": "Required" }
}
Serve problem details with application/problem+json and make the HTTP status match the status member. title describes the problem class and should remain stable; detail can explain this occurrence without exposing internals. A stable type URI lets clients recognize a class without parsing English text.
Use extensions for structured data such as field errors and a request ID. Clients must still tolerate new extension fields. Centralize unexpected exceptions so they become one generic 500 response and one detailed server log, not several leaked stack traces. Test the helper’s status, media type, required fields, and absence of SQL, file paths, and secret values.
Create one helper that returns problem JSON and use it for 404 and invalid-input responses.
Lesson completed