nautechsystems/nautilus_trader · critical · anyhow::Error

Postgres execution requires protected payload storage

Error message

Postgres execution requires protected payload storage

What it means

`require_execution_payload_storage` authenticates that signed-transaction payloads are stored in protected storage before any execution action. After checking readiness it inspects storage with the given keys/policy and throws this error when `check.protected` is false — i.e. the schema is ready but the storage fails the protection check (e.g. active key not configured/validated).

Source

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

                ),
            }
        }

        self.validate_execution_payload_ready(keys).await
    }

    /// Requires ready protected storage and authenticates every persisted signed payload.
    pub(crate) async fn require_execution_payload_storage(
        &self,
        keys: &PayloadKeySet,
        policy: PayloadPolicy,
        batch_size: i64,
    ) -> anyhow::Result<ExecutionPayloadLease> {
        self.require_execution_payload_storage_ready(keys).await?;
        let (check, transaction) = self
            .inspect_execution_payload_storage(Some(keys), Some(policy), batch_size)
            .await?;
        anyhow::ensure!(
            check.protected,
            "Postgres execution requires protected payload storage"
        );
        Ok(ExecutionPayloadLease {
            _transaction: transaction,
        })
    }

    /// Requires protected storage to be ready before execution schema initialization.
    pub(crate) async fn require_execution_payload_storage_ready(
        &self,
        keys: &PayloadKeySet,
    ) -> anyhow::Result<()> {
        anyhow::ensure!(
            self.execution_payload_marker().await?.is_some(),
            "Postgres execution requires protected payload storage"
        );
        self.validate_execution_payload_ready(keys).await

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Run `ensure_execution_payload_storage` at startup so activation/migration completes before execution
  2. Verify the PayloadKeySet contains the correct deployment id and active key id matching execution_payload_state.active_key_id
  3. Inspect the check output from inspect_execution_payload_storage to see which protection condition failed
  4. Confirm node config enables protected payload storage and points at the right database

Example fix

// before: executing without completing activation
let lease = db.require_execution_payload_storage(&keys, policy, batch).await?;
// after: ensure storage first
db.ensure_execution_payload_storage(&keys).await?;
let lease = db.require_execution_payload_storage(&keys, policy, batch).await?;
Defensive patterns

Strategy: validation

Validate before calling

let (check, _) = db.inspect_execution_payload_storage(Some(&keys), None, 1).await?;
if !check.protected {
    return Err(anyhow::anyhow!("payload storage is not protected; run ensure_execution_payload_storage before executing"));
}

Try / catch

match db.require_execution_payload_storage(&keys, policy, batch).await {
    Err(e) if e.to_string().contains("requires protected payload storage") => {
        // activate protection, verify keys match active_key_id, then retry once
        db.ensure_execution_payload_storage(&keys).await?;
        db.require_execution_payload_storage(&keys, policy, batch).await?;
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling an execution path that acquires a payload lease when `inspect_execution_payload_storage(Some(keys), Some(policy), batch_size)` reports `protected == false`: missing or mismatched payload key in PayloadKeySet, encryption/protection not fully activated, or policy not satisfied by current storage state.

Common situations: Starting a live execution node against a database where payload protection was never fully activated; rotating keys but the PayloadKeySet passed to the node lacks the new active key; running with a config that disables protection while the code path requires it.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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