# Turning one failure into another

A failure can come from something the compiler knows can go wrong, such
as a read that finds nothing, a write that breaks a unique rule or a
construction, or from another call. You turn it into your own failure
with `condition: Failure` in the operation's block. The failure's kind
must fit the condition:

| Condition | Required kind |
|---|---|
| `missing:` | `not_found` |
| `conflict:` | `conflict` |
| `empty:` (a patch that changes nothing) | `invalid_value` |
| A construction's rule keys, such as `max:`, and `invalid:` covering the rest | `invalid_value` |

## A read that finds nothing: `missing:`

A query names the failure for a record that isn't there
([Named queries](named-queries.md)):

```jadpo
query todo_by_id(todo_id: Todo.id) fails TodoNotFound -> TodoView {
    from: Todo
    where: Todo.id == todo_id
    missing: TodoNotFound {
        todo_id: todo_id
    }
}
```

## A value built at run time: rule keys and `invalid:`

A construction is keyed by the rule that can break
([Construction failures by rule](creating-values.md#construction-failures-by-rule)):

```jadpo
var quantity: Quantity = attempt Quantity(count) {
    max: QuantityTooLarge
    invalid: QuantityOutOfRange
}
```

`invalid:` is the catch-all only for a construction's rules. A read's, a
write's or an integration call's conditions each need their own arm, and
`invalid:` in their block is the error
`failure.invalid_outside_construction`.

## A write that breaks a unique rule: `conflict:`

A write names a failure for each unique field it could clash on
([When a write is refused](when-a-write-is-refused.md)):

```jadpo
var account: Account = attempt Account.create {
    set: {
        ...
    }
    conflict: {
        Account.handle: HandleTaken
    }
}
```

## A failure from a call: `match`

A `match` on the call gives each of its failures an arm
([Handling a failure in `match`](handling-a-failure-in-match.md)):

```jadpo
var receipt: Receipt = match payments.charge(order) {
    success(receipt) -> receipt
    CardDeclined -> reject PaymentDeclined
}
```

## Decoding JSON

`json.read` fails with `mismatch` when the JSON doesn't fit the type
([`json`](json.md)). When the failure you map
`mismatch` to declares the field `problem: DecodeProblem`, Jadpo fills it
with the first problem found. So the arm gives every other field of the
failure, and never `problem`. No other mapping fills a `DecodeProblem`
field.

## The original failure is kept

The failure that was mapped is kept as the internal cause of the new one,
so the log shows both:

```text
PaymentDeclined rejected at domains/checkout/actions/pay.jadpo:14
  caused by CardDeclined from payments.charge (internal: decline_code)
  propagated through route POST /checkout
```
