# `step.encryption_key_required`

An action makes several changing calls, but the app names no key to encrypt the answers it keeps from them.

Area 12, [Background work](/docs/jobs-and-events.md); not declinable; the next step is usually the human's.

## Why Jadpo refuses it

When an action makes several changing calls, Jadpo keeps each call's
answer until the action commits, so a retry can replay it rather than
send the call again. Those answers can hold anything a provider sends
back, so they are kept encrypted, with the `SigningKey` setting that
`application { steps: { encryption_key: } }` names. Without one there
is no key to encrypt them with. Jadpo won't make up a secret for you:
the setting is a new value each environment has to be given. The error is
reported once, at the first action that needs the key.

## What it looks like

domains/bakery/actions/file_prices.jadpo, in a bakery app that names no
key in `app.jadpo`:








```jadpo
use app { sheets }
use bakery/failures { SheetNotKept }
use bakery/events { PricesChanged }

/// Keeps a supplier's new prices as a sheet, then a copy for the
/// accountant.
action file_prices(event: PricesChanged) fails SheetNotKept -> Unit {
    var sheet: File = attempt sheets.put(encoding.to_utf8(event.price_list), FileType.csv) {
        storage_full: SheetNotKept
    }
    var invoice_copy: File = attempt sheets.put(encoding.to_utf8(event.price_list), FileType.csv) {
        storage_full: SheetNotKept
    }
    assert sheet != invoice_copy
}
```

```text
error: `file_prices` makes 2 changing calls, but `app.jadpo` names no key to encrypt their answers with
 --> domains/bakery/actions/file_prices.jadpo:8:31
  |
8 |     var sheet: File = attempt sheets.put(encoding.to_utf8(event.price_list), FileType.csv) {
  |                               ^^^^^^^^^^ its answers are kept
  reason: Each answer of an action with several changing calls is kept, encrypted, until the action commits, so a retry can replay it; `application { steps: { encryption_key: } }` names the `SigningKey` setting it is encrypted with, and `file_prices` is the first action that needs it.
  next: Add `steps: { encryption_key: config.step_encryption_key }` to `application { }` in `app.jadpo`, and declare `step_encryption_key: SigningKey` in `config.jadpo` (human)
  rule: step.encryption_key_required
  help: https://jadpo.dev/docs/errors/step.encryption_key_required

check failed: 1 error, 7 files
```

`(human)` at the end of the `next:` line tells your coding agent to stop
and ask you which fix you want, because the choice is yours to make: it
decides a new secret setting that each environment must be given.

## How to fix it

**If these answers should be kept**, name a `SigningKey` setting in
`steps:` in `app.jadpo`:

```jadpo
    steps: {
        encryption_key: config.step_encryption_key
    }
```








Then declare the setting in `config.jadpo`, which becomes:

```jadpo
config {
    main_url: PostgresUrl
    step_encryption_key: SigningKey
}
```

The answers of `file_prices`'s calls are now kept encrypted with the key
in `STEP_ENCRYPTION_KEY`, which must be at least 32 characters with no
spaces and is checked when the app starts.

## Related

- [How the record is kept](/docs/several-changing-calls-in-one-action.md#how-the-record-is-kept)
- [The record](/docs/several-changing-calls-in-one-action.md#the-record)
- [Signing keys](/docs/signing-keys.md)
- [Secrets](/docs/secrets.md)
