nautechsystems/nautilus_trader · error · anyhow::Error

Execution payload rollback state is missing

Error message

Execution payload rollback state is missing

What it means

The finalize/complete phase of an execution payload rollback locks execution_payload_state for component 'signed_transactions' and requires it to exist with operation == 'rollback'. This error is thrown when the state row is absent, meaning a rollback is not in progress so there is no rollback state to complete.

Source

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

    async fn rollback_execution_payload_batch(
        &self,
        keys: &PayloadKeySet,
        batch_size: i64,
    ) -> anyhow::Result<bool> {
        let mut transaction = self
            .pool
            .begin()
            .await
            .context("failed to start execution payload rollback batch")?;
        lock_execution_payload_operation(&mut transaction).await?;
        let state_row = sqlx::query(
            "SELECT deployment_id, protocol_version, operation, active_key_id \
             FROM execution_payload_state WHERE component = 'signed_transactions' FOR UPDATE",
        )
        .fetch_optional(&mut *transaction)
        .await
        .context("failed to lock execution payload rollback state")?
        .ok_or_else(|| anyhow::anyhow!("Execution payload rollback state is missing"))?;
        let state = execution_payload_state_from_row(&state_row)?;
        validate_execution_payload_state(&state, keys)?;
        anyhow::ensure!(
            state.operation == "rollback",
            "Execution payload storage is not rolling back"
        );
        let rows = sqlx::query_as::<_, ExecutionTransactionHashRow>(
            "
            SELECT
                id, intent_id, chain_id, transaction_hash, payload_expected,
                raw_transaction, sealed_transaction, status, block_number, block_hash,
                receipt_success, gas_used, effective_gas_price, current
            FROM execution_transaction_hash
            WHERE payload_expected AND sealed_transaction IS NOT NULL
            ORDER BY id
            LIMIT $1
            FOR UPDATE
            ",

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Start the rollback first (begin_execution_payload_rollback via rollback_execution_payload_storage) before invoking the finalization step
  2. If the rollback already completed, skip finalization — check updated_at/operation history to confirm
  3. Confirm the finalization call targets the same database/schema where the rollback was started

Example fix

// before
complete_execution_payload_rollback(&keys).await?;
// after: ensure rollback is in progress first
let state = fetch_execution_payload_state(&db).await?;
if state.map(|s| s.operation == "rollback").unwrap_or(false) {
    complete_execution_payload_rollback(&keys).await?;
}
Defensive patterns

Strategy: validation

Validate before calling

let state = sqlx::query(
    "SELECT operation FROM execution_payload_state WHERE component = 'signed_transactions'")
    .fetch_optional(&db).await?;
let in_rollback = state.map(|s| s.operation == "rollback").unwrap_or(false);
if !in_rollback { /* skip or start rollback first */ }

Prevention

When it happens

Trigger: Calling the rollback-finalization routine without having first called begin_execution_payload_rollback; the state row was deleted after a prior rollback completed; running finalize against a different database than the one where the rollback began.

Common situations: Re-running a rollback completion after it already finished and cleaned up state; a crashed/interrupted deployment where the state row was manually removed; mixing environments (staging DB connection used to finalize a production rollback).

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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