# Declaring a failure

A failure is a way an action or query can fail that its caller is
expected to handle, such as stock running out. You declare it as a type
whose base is `Failure`, and raise it with `reject`. Save this as
`main.jadpo` and run `jadpo test main.jadpo`:

```jadpo
/// There isn't enough stock to fill the order.
type OutOfStock = Failure {
    kind: FailureKind.conflict
    message: "There isn't enough stock."
}

type Stock = Int {
    min: 0
}

/// The stock left once one item is sold.
function after_sale(stock: Stock) fails OutOfStock -> Stock {
    if (stock == 0) {
        reject OutOfStock
    }
    return Stock(stock - 1)
}

test "the last one sells, and then there are none" {
    var left: Stock = attempt after_sale(1)
    assert left == 0
    assert after_sale(0) fails OutOfStock
}
```

`Failure`, `FailureKind` and `Int` are built in. `OutOfStock`, `Stock` and
`after_sale` are defined here. `fails OutOfStock` says the function can fail
this way, and `reject` raises the failure.

The `///` line above `OutOfStock` is a documentation comment. It is
optional, and becomes the failure's description in generated documentation
and OpenAPI.

The base, `Failure`, gives the type its settings: `kind`, `message`,
`client`, `internal` and, rarely, `code`.

## `kind:`, which sets the status

`kind:` names one of the [failure kinds](/docs/failure-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](/docs/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.

Here are two failures with fields. `Todo` and `Product` are entities, kinds
of stored record, declared with `Quantity` in another file of the app. A
field typed `Todo.id` has the type of `Todo`'s `id` field.

```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
    }
}
```

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](/docs/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](/docs/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](/docs/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`](/docs/handling-a-failure-in-match.md), write `public` before the
declaration: `public type QuantityUnavailable = Failure { ... }`.
