# What the client sees

Every failure reaches an HTTP client in the same envelope. The failure's
client fields appear under `details`:

```json
{
  "error": {
    "code": "quantity_unavailable",
    "message": "The requested quantity is unavailable.",
    "request_id": "req_0b1e…",
    "details": {
      "available": 5
    }
  }
}
```

Internal fields, stacks, SQL, provider text and source locations never
appear.

Request input that breaks a rule is reported with the field and the rule
it broke, never the value
([How failures reach the client](how-failures-reach-the-client.md)):

```json
{
  "error": {
    "code": "invalid_input",
    "message": "Request body value is invalid.",
    "request_id": "req_0b1e…",
    "details": {
      "problems": [
        { "field": "title", "rule": "max_length" },
        { "field": "due_at", "rule": "required" }
      ]
    }
  }
}
```

The generated OpenAPI lists every failure a route can reach, under its
status. `build/compatibility/public-failure-codes.json` records each
public code with its status, message and client fields. Changing any of
them is a breaking change.
