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).awaitView on GitHub (pinned to 18893faf8b)
Solutions
- Run `ensure_execution_payload_storage` at startup so activation/migration completes before execution
- Verify the PayloadKeySet contains the correct deployment id and active key id matching execution_payload_state.active_key_id
- Inspect the check output from inspect_execution_payload_storage to see which protection condition failed
- 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
- Always call ensure_execution_payload_storage at node startup before execution paths
- Keep PayloadKeySet in sync with the deployment id and active key id in the database
- Enable protected storage in configuration for any live execution node
- Re-run the protection check after key rotation
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
- Execution payload protection is active, but no payload key i
- Protected execution transaction {} contains plaintext
- Execution payload rewrap state is missing
- Execution payload rewrap left {remaining} row(s)
- Invalid config type for AxExecutionClientFactory. Expected A
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/6b1baf1bc5af29a8.
Report an issue: GitHub.