nautechsystems/nautilus_trader · error · anyhow::Error

Execution transaction {} requires an unavailable payload key

Error message

Execution transaction {} requires an unavailable payload key

What it means

The row carries a sealed envelope whose header names a payload key id, but that key id is not present in the PayloadKeySet supplied to the loader. Without the key the envelope cannot be unsealed, so the ensure! fails fast instead of silently dropping the transaction.

Source

Thrown at crates/adapters/blockchain/src/cache/database.rs:5237

                }
                original_rows += 1;
                let intent = load_execution_intent(&mut transaction, hash.intent_id).await?;
                let raw_transaction = if let (Some(keys), Some(deployment_id)) =
                    (keys, deployment_id.as_deref())
                {
                    anyhow::ensure!(
                        hash.raw_transaction.is_none(),
                        "Protected execution transaction {} contains plaintext",
                        hash.id
                    );
                    let envelope = hash.sealed_transaction.as_deref().ok_or_else(|| {
                        anyhow::anyhow!(
                            "Protected execution transaction {} has no envelope",
                            hash.id
                        )
                    })?;
                    let key_id = envelope_key_id(envelope)?;
                    anyhow::ensure!(
                        keys.contains_key(&key_id),
                        "Execution transaction {} requires an unavailable payload key",
                        hash.id
                    );
                    key_ids.insert(alloy::hex::encode(key_id));
                    let context = payload_context(&intent, hash, deployment_id)?;
                    keys.unseal(envelope, &context)?
                } else {
                    anyhow::ensure!(
                        hash.sealed_transaction.is_none(),
                        "Legacy execution transaction {} contains an envelope",
                        hash.id
                    );
                    hash.raw_transaction.clone().ok_or_else(|| {
                        anyhow::anyhow!("Legacy execution transaction {} has no plaintext", hash.id)
                    })?
                };
                authenticate_retained_payload(

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Add the missing payload key (id from the error's key id) to the PayloadKeySet before loading.
  2. Import the retired wrapping key from your secret manager / backup so old envelopes remain decryptable.
  3. Re-run rewrap_execution_payload_storage with a key set that includes both old and new active keys so envelopes are rewrapped to the current key.
  4. Verify key configuration matches execution_payload_state.active_key_id and deployment_id.

Example fix

// before: key set missing retired key
let keys = PayloadKeySet::new(active_key);
// after: include retained old keys during rotation window
let keys = PayloadKeySet::builder()
    .active_key(new_key)
    .retained_key(old_key) // key id referenced by existing envelopes
    .build();
Defensive patterns

Strategy: fallback

Validate before calling

// Ensure all envelope key ids are covered before loading
for key_id in collect_envelope_key_ids(&rows)? {
    if !keys.contains_key(&key_id) {
        return Err(anyhow!("payload key {} missing from key set", alloy::hex::encode(key_id)));
    }
}

Prevention

When it happens

Trigger: Loading protected execution transactions where envelope_key_id(envelope) returns a key id absent from the provided keys map — e.g. the key was rotated out of the config, or a stale/old wrapping key was never imported.

Common situations: Key rotation completed on the database side but the node's key configuration still lacks the retired key; a fresh environment missing legacy keys from a secret store; copying a database between deployments with different key inventories.

Related errors


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