# Describing Errors Consistently — OpenAPI / Swagger

Source: https://www.skillbyai.com/en/openapi/sec-errors

> Model error responses with Problem Details and reusable responses.

## Errors are part of the contract

Clients spend much of their integration effort on errors, so describe them as carefully as success responses. Use **one consistent error format** across the API. A widely adopted standard is **Problem Details for HTTP APIs** (**RFC 9457**, which obsoletes RFC 7807), with media type `application/problem+json` and fields `type` (a URI identifying the problem type), `title`, `status`, `detail` and `instance`, plus extension members such as `errors` for field-level validation messages or `traceId`. Define the error schema once in `components/schemas` and reusable **responses** (`BadRequest`, `Unauthorized`, `Forbidden`, `NotFound`, `Conflict`, `ValidationProblem`, `TooManyRequests`, `ServerError`) in `components/responses`, then reference them from every operation. Include **examples** of real error bodies. Document **headers** relevant to errors, such as `Retry-After` on 429 and 503. Avoid leaking internal details (stack traces, SQL) in error messages, and keep `type` URIs stable so clients can branch on them.

## Problem Details schema and reusable error responses

One error shape everywhere, with field-level validation details.

```yaml
components:
  schemas:
    Problem:
      type: object
      required: [type, title, status]
      properties:
        type: { type: string, format: uri, examples: ['https://api.example.com/problems/validation'] }
        title: { type: string }
        status: { type: integer }
        detail: { type: string }
        instance: { type: string }
        traceId: { type: string }
        errors:
          type: array
          items:
            type: object
            required: [field, message]
            properties:
              field: { type: string, examples: ['items[0].quantity'] }
              message: { type: string, examples: ['must be between 1 and 99'] }

  responses:
    ValidationProblem:
      description: The request body or parameters are invalid
      content:
        application/problem+json:
          schema: { $ref: '#/components/schemas/Problem' }
          examples:
            badQuantity:
              value:
                type: https://api.example.com/problems/validation
                title: Invalid request
                status: 422
                errors: [{ field: 'items[0].quantity', message: 'must be between 1 and 99' }]
    TooManyRequests:
      description: Rate limit exceeded
      headers:
        Retry-After: { schema: { type: integer }, description: Seconds to wait }
      content:
        application/problem+json:
          schema: { $ref: '#/components/schemas/Problem' }
```

## Use a default response sparingly

A `default` response can catch undocumented errors, but it is no substitute for listing the specific status codes clients must handle. Specific codes generate clearer SDK types and documentation.

**Quiz:** Which RFC defines Problem Details for HTTP APIs in its current version?

- [x] RFC 9457
- [ ] RFC 2616
- [ ] RFC 6749
- [ ] RFC 7519

*Answer:* RFC 9457. RFC 9457 is the current Problem Details standard, obsoleting RFC 7807.
