# Declaring a failure

A failure is a way an action or query can fail that its caller is
expected to handle, such as a todo that doesn't exist. You declare it as a
type whose base is `Failure`, written `type TodoNotFound = Failure { ... }`.
The base gives the type its settings: `kind`, `message`, `client`,
`internal` and, rarely, `code`. Here are two failures, with the `Todo` and
`Product` entities (stored records) and the `Quantity` type they refer to
declared elsewhere:

```jadpo
/// The todo does not exist.
type TodoNotFound = Failure {
    kind: FailureKind.not_found
    message: "Todo not found."
    internal: {
        todo_id: Todo.id
    }
}

type QuantityUnavailable = Failure {
    kind: FailureKind.conflict
    message: "The requested quantity is unavailable."
    client: {
        available: Quantity
    }
    internal: {
        product_id: Product.id
        requested: Quantity
    }
}
```

The `///` line above `TodoNotFound` is a documentation comment. It is
optional, and becomes the failure's description in generated documentation
and OpenAPI. A field typed `Todo.id` has the type of `Todo`'s `id` field.

## `kind:`, which sets the status

`kind:` names one of the [kinds](kinds.md), the categories a failure falls
into, such as `not_found` or `conflict`. The kind sets the HTTP status a
client gets, and how background work, such as a
[job or an event subscriber](jobs-and-events.md), treats the failure. A failure never states a status itself.

## The code clients see

A failure's public code is its name in lower_snake_case: `TodoNotFound`
is `todo_not_found`. Clients rely on it, so it stays the same. Write
`code: "todo_missing"` only to keep a code clients already use after you
rename the failure.

## `message:`

`message:` is fixed text that is safe to show anyone. It can't include
values. Leave it out and the client gets the generic message Jadpo keeps
for the failure's kind.

## `client:` and `internal:` fields

A failure can carry values that say what went wrong, such as which
product ran out. These are its fields, and they go in one of two blocks:

- `client: { }` holds the fields sent to the caller.
- `internal: { }` holds the fields that never leave the server. They are
  for your logs and traces.

A field name can't be in both. A failure has no fields outside these two
blocks. The caller gets a JSON body with `code`, `message`, `request_id`
and, when the failure has `client` fields, those fields under `details`
([How failures reach the client](how-failures-reach-the-client.md)).
Leave `client` out and the body has only the code, the message and the
request id.

These fields are ordinary fields. A `T?` type, which may hold no
value, is allowed. `optional` and `default` are not, because only `Input`
types may have them ([One form for every type](one-form-for-every-type.md)).

## Where the file goes

An app's code is split into domains: one business area each, such as
`planning`, in a folder under `domains/`
([Project layout](project-layout.md)). Each
failure has its own file in its domain's `failures/` folder, such as
`domains/planning/failures/todo_not_found.jadpo`.

When the actions of two or more domains can fail with the same failure,
you put its file in `shared/failures/` instead. When code in another
domain handles the failure, for example in a
[`match`](handling-a-failure-in-match.md), write `public` before the
declaration: `public type QuantityUnavailable = Failure { ... }`.
