nautechsystems/nautilus_trader · error · anyhow::Error
Payload rollback requires an active payload key
Error message
Payload rollback requires an active payload key
What it means
rollback_payload_storage() decrypts authenticated plaintext payloads and removes protection, requiring the active payload key set to authenticate the stored ciphertext. When load_payload_keys() returns None the rollback cannot proceed and the client refuses the operation rather than leaving the storage in a half-protected state.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:919
.rewrap_execution_payload_storage(&keys, batch_size)
.await
}
/// Restores authenticated plaintext payloads and removes protection from this database.
///
/// This incident-only operation is resumable. Keep the complete key set configured until it
/// succeeds and the unprotected database passes a full payload check.
///
/// # Errors
///
/// Returns an error if the client is connected, storage is not protected, required keys are
/// unavailable, or any bounded rollback batch fails authentication.
pub async fn rollback_payload_storage(&self, batch_size: usize) -> anyhow::Result<()> {
let batch_size = validate_payload_operation_batch_size(batch_size)?;
let database = self.payload_operation_database().await?;
let keys = self
.load_payload_keys()?
.ok_or_else(|| anyhow::anyhow!("Payload rollback requires an active payload key"))?;
database
.rollback_execution_payload_storage(&keys, batch_size)
.await
}
async fn payload_operation_database(&self) -> anyhow::Result<BlockchainCacheDatabase> {
anyhow::ensure!(
!self.core.is_connected(),
"Disconnect the execution client before payload storage operations"
);
if let Some(database) = &self.cache.database {
return Ok(database.clone());
}
let options = self
.config
.postgres_cache_database_config
.as_ref()View on GitHub (pinned to 18893faf8b)
Solutions
- Initialize keys first with protect_payload_storage(), or load them via the normal connect flow, then rollback.
- Use check_payload_storage() to confirm keys exist and protection state before rolling back.
- Fix key store configuration so load_payload_keys() resolves the persisted keys.
- If the storage was never protected, no rollback is needed — skip the call.
Example fix
// before
client.rollback_payload_storage(500).await?;
// after
anyhow::ensure!(
client.check_payload_storage().await?.has_keys,
"initialize keys before rollback"
);
client.rollback_payload_storage(500).await?; Defensive patterns
Strategy: validation
Validate before calling
let status = client.check_payload_storage().await?; anyhow::ensure!(status.has_keys, "payload storage has no keys; nothing to rollback"); client.rollback_payload_storage(batch_size).await?;
Prevention
- Only roll back databases previously protected.
- Check protection state via check_payload_storage() before rollback.
- Keep key store configuration stable across deploys.
When it happens
Trigger: Calling client.rollback_payload_storage(batch_size) when no payload keys were loaded (never protected, keys cleared, or key store unavailable).
Common situations: Attempting rollback on a database that was never protected; running rollback from a client instance whose connect sequence did not initialize keys; key store misconfiguration after redeploy.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- Payload rewrap requires an active payload key
- Execution payload storage is in {operation} maintenance; com
- Execution payload protection is active, but no payload key i
- Execution payload storage is in {operation} maintenance, not
- Execution payload storage is in {operation} maintenance, not
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/dac3fb3e2b5f5b82.
Report an issue: GitHub.