> ## Documentation Index
> Fetch the complete documentation index at: https://docs-pos.solya.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Error codes

> The kernel ResultCode values, how they map to HTTP status, and how error responses are derived.

Every failure returns the [error envelope](/en/developers/making-requests#the-error-envelope)
with a machine-readable `code`. That `code` is a kernel `ResultCode`, and each code
maps to exactly one HTTP status. **Branch on `code`, not on `message`.**

## The ResultCode → HTTP status map

| `code`                    | HTTP  | Meaning                                                                                       |
| ------------------------- | ----- | --------------------------------------------------------------------------------------------- |
| `VALIDATION_FAILED`       | `400` | The request shape or values were rejected; carries `fieldErrors`.                             |
| `UNAUTHORIZED`            | `401` | Missing or invalid bearer token.                                                              |
| `FORBIDDEN`               | `403` | Valid token, but it lacks the required `pos.*` scope.                                         |
| `NOT_FOUND`               | `404` | The addressed resource does not exist.                                                        |
| `CONFLICT`                | `409` | The request conflicts with current state (e.g. a stale expected version).                     |
| `BUSINESS_RULE_VIOLATION` | `422` | A well-formed request that violates a domain rule (e.g. an empty cart, an unsettled balance). |
| `INTERNAL_ERROR`          | `500` | An unexpected server-side failure.                                                            |

`OK` is the success code (`200`); it never appears in an error body — the error
`code` enum is the set of every `ResultCode` except `OK`.

## How error responses are derived

Error responses are not hand-written per route; they are derived from the code→status
map above, so the documented errors match what the server actually returns:

* **`400` and `500`** are always possible.
* **`401`** when the operation is authenticated.
* **`403`** when the operation is scope-gated.
* **`404`** when the path addresses a single resource (has an id param).
* **`409`** for a conflict route.
* **`422`** for a business-rule mutation.

## Validation errors

A `VALIDATION_FAILED` body carries a `fieldErrors` array — one `{ field, message }`
per rejected field, where `field` is the dot-path of the offending field. Use it to
map failures back onto a form:

```json theme={null}
{
  "error": {
    "code": "VALIDATION_FAILED",
    "message": "…",
    "statusCode": 400,
    "fieldErrors": [
      { "field": "lines.0.quantity", "message": "must be positive" }
    ]
  }
}
```

Runtime validation failures are normalized into this exact envelope, identical to a
domain use-case rejection — you handle both the same way.
