nautechsystems/nautilus_trader · error

Payload sealing key {} is not configured

Error message

Payload sealing key {} is not configured

What it means

Thrown in `unseal` when the envelope's embedded key ID does not match any key in the currently configured key set, so the payload cannot be decrypted. The library keeps only configured keys and refuses to look up unknown identifiers.

Source

Thrown at crates/adapters/blockchain/src/execution/sealing.rs:195

            .map_err(|_| anyhow::anyhow!("Failed to seal signed transaction payload"))?;

        let mut envelope = Vec::with_capacity(ENVELOPE_HEADER_LEN + ciphertext.len());
        envelope.push(ENVELOPE_VERSION);
        envelope.extend_from_slice(&self.active_id);
        envelope.extend_from_slice(nonce.as_ref());
        envelope.extend_from_slice(&ciphertext);
        Ok(envelope)
    }

    pub(crate) fn unseal(
        &self,
        envelope: &[u8],
        context: &PayloadContext,
    ) -> anyhow::Result<Vec<u8>> {
        validate_context(context, &self.deployment_id)?;
        let parsed = parse_envelope(envelope)?;
        let key = self.keys.get(&parsed.key_id).ok_or_else(|| {
            anyhow::anyhow!(
                "Payload sealing key {} is not configured",
                hex::encode(parsed.key_id)
            )
        })?;
        let aad = encode_aad(&parsed.key_id, context)?;
        let nonce = Nonce::try_assume_unique_for_key(parsed.nonce)
            .map_err(|_| anyhow::anyhow!("Signed transaction payload nonce is invalid"))?;
        let mut plaintext = parsed.ciphertext_and_tag.to_vec();
        let plaintext_len = key
            .open_in_place(nonce, Aad::from(aad), &mut plaintext)
            .map_err(|_| anyhow::anyhow!("Signed transaction payload authentication failed"))?
            .len();
        plaintext.truncate(plaintext_len);
        anyhow::ensure!(
            plaintext.len() <= MAX_SIGNED_TRANSACTION_BYTES,
            "Unsealed transaction payload is {} bytes, exceeding the {} byte limit",
            plaintext.len(),
            MAX_SIGNED_TRANSACTION_BYTES

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Re-add the key for the envelope's key ID to the key-set configuration and retry unsealing
  2. Check the key ID (hex in the message) against your key-rotation history to identify which environment's key is missing
  3. Confirm the envelope belongs to this deployment_id; if from another deployment, use that deployment's keys

Example fix

// before
retired_envs = [] // old key removed before old payloads were unsealed
// after
retired_envs = ["env-2024-q3"] // keep retired keys until all envelopes are rewrapped
Defensive patterns

Strategy: validation

Validate before calling

let parsed = parse_envelope(envelope)?;
if !key_set.contains_key(&parsed.key_id) {
    return Err(anyhow!("key {} missing; cannot unseal", hex::encode(parsed.key_id)));
}

Try / catch

match sealer.unseal(&envelope, &ctx) {
    Ok(pt) => pt,
    Err(e) if e.to_string().contains("not configured") => {
        reload_keys_with_retained_retirements()?;
        sealer.unseal(&envelope, &ctx)?
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `unseal` (directly or via migrate/rewrap/rollback/open execution payload functions) with an envelope sealed under a key ID absent from `self.keys` — e.g. a key was rotated out of the set or the envelope comes from another deployment.

Common situations: Key rotation removed the old environment's key while envelopes sealed under it still exist; restoring from a backup of a different `deployment_id`; cross-environment payload migration without carrying the old key.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/cdbb356a880f2f39. Report an issue: GitHub.