Errors are part of the contract
Callers spend as much code handling failures as successes, so errors deserve a deliberate shape. A vague message forces guesswork and brittle string matching.
What a good error carries
- The right status code: 4xx for caller mistakes, 5xx for server faults.
- A stable, machine readable error code the client can branch on.
- A human readable message for the developer reading logs.
- Optional details, like which fields failed validation.
Status code discipline
Map causes correctly so clients react well. A bad input is 400, missing authentication is 401, forbidden access is 403, a missing resource is 404, and an unexpected fault is 500. Returning 200 with an error body inside is a classic trap that breaks generic clients.
Keep the error code stable even if you reword the message, because clients depend on the code, not the prose.
Key idea
Return the correct status, a stable machine readable code, and a clear message so clients and humans both recover.