HomeBytesheetsRoadmapsUI TemplatesUI ToolsStack Discussion
3 Topics
Chapter•140 Minutes

API Errors and Problem Details

Create predictable, machine-readable, secure error responses.

Types of API Errors

Errors can originate from validation, authentication, authorization, resource existence, business conflicts, rate limits, dependency failures, timeouts, or unexpected server faults.

Do not expose internal stack traces, SQL statements, secrets, filesystem paths, or dependency details to clients in production.

A useful API distinguishes between errors that clients can fix and errors that require server-side intervention.

Error Categories
400: Malformed or invalid request
The request cannot be processed as submitted.
401: Authentication failure
Credentials are missing or invalid.
403: Authorization failure
The caller lacks permission.
409: Conflict
The request conflicts with current resource state.
422: Semantic validation failure
The syntax is valid but business validation fails.
500: Unexpected server error
The server encountered an unhandled failure.

Machine-Readable Error Responses

Standard Error Format

Define one predictable error structure across the API.

A useful structure can contain a machine-readable type, human-readable title, HTTP status, safe detail, and an instance identifying the request or error occurrence.

For validation failures, include structured field-level information so clients can highlight invalid inputs without parsing human-readable strings.

The error contract itself is part of your public API and should be documented.

Problem Details Style Error
{
  "type": "https://api.example.com/problems/validation-error",
  "title": "Validation failed",
  "status": 422,
  "detail": "One or more fields are invalid.",
  "errors": [
    {
      "field": "email",
      "code": "invalid_format",
      "message": "Enter a valid email address."
    }
  ],
  "requestId": "req_01HXYZ"
}
💡 The response separates machine-readable information from human-readable messages and provides request correlation.

Centralized Error Handling

Business services should throw meaningful domain errors rather than constructing HTTP responses throughout the application.

The HTTP layer maps known domain errors to status codes. Unexpected errors become generic 500 responses while the complete diagnostic information is logged internally.

This separation makes services reusable outside HTTP and ensures that every endpoint follows the same error contract.

Express Error Middleware
app.use((err, req, res, next) => {
  req.log.error({ err }, 'Unhandled API error');

  if (err.code === 'USER_NOT_FOUND') {
    return res.status(404).json({
      type: 'user-not-found',
      title: 'User not found',
      status: 404
    });
  }

  res.status(500).json({
    type: 'internal-error',
    title: 'Internal Server Error',
    status: 500,
    requestId: req.id
  });
});
💡 Known application errors are translated into stable API responses while unexpected implementation details remain internal.