nautechsystems/nautilus_trader · error · anyhow::Error

Execution payload storage is {}, not migrating

Error message

Execution payload storage is {}, not migrating

What it means

Migration batches are only valid while execution_payload_state.operation == 'migrate'. If the state records any other operation (e.g. 'ready' or an activation step), the driver refuses to run migration work, preventing migration logic from executing outside its sanctioned lifecycle phase.

Source

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

            "Execution payload batch size must be positive"
        );
        let mut transaction = self
            .pool
            .begin()
            .await
            .context("failed to start execution payload migration 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 migration state")?
        .ok_or_else(|| anyhow::anyhow!("Execution payload migration state is missing"))?;
        let state = execution_payload_state_from_row(&state_row)?;
        validate_execution_payload_state(&state, keys)?;
        anyhow::ensure!(
            state.operation == "migrate",
            "Execution payload storage is {}, not migrating",
            state.operation
        );

        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 raw_transaction IS NOT NULL
            ORDER BY id
            LIMIT $1
            FOR UPDATE
            ",
        )

View on GitHub (pinned to 18893faf8b)

Solutions

  1. If the store is already 'ready', migration is done — stop re-running the migrator
  2. If it is in another maintenance phase, complete or abort that phase first, then enter migration properly via the library's lifecycle API
  3. Inspect SELECT operation FROM execution_payload_state WHERE component='signed_transactions' to see the current phase
  4. Only drive operation transitions through the library's activate/migrate/complete functions

Example fix

// before: unconditional migration
while db.migrate_execution_payload_batch(&keys, 500).await? {}
// after: only migrate when in migrate phase
if db.execution_payload_state().await?.map(|s| s.operation).as_deref() == Some("migrate") {
    while db.migrate_execution_payload_batch(&keys, 500).await? {}
}
Defensive patterns

Strategy: validation

Validate before calling

let op: Option<String> = sqlx::query_scalar(
    "SELECT operation FROM execution_payload_state WHERE component = 'signed_transactions'",
).fetch_optional(&pool).await?;
let can_migrate = op.as_deref() == Some("migrate");

Type guard

fn is_migrating(op: &str) -> bool { op == "migrate" }

Try / catch

match db.migrate_execution_payload_batch(&keys, 500).await {
    Ok(_) => {}
    Err(e) if e.to_string().contains("not migrating") => {
        // storage already ready or in another phase; stop or re-enter lifecycle correctly
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling migrate_execution_payload_batch when the state row exists and validates but operation != 'migrate' — e.g. storage is already fully migrated ('ready') or is in another maintenance phase.

Common situations: Re-running migration tooling after migration already completed; another operator switched the operation column; activation still in progress when the migrator started.

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/507296bebed299bf. Report an issue: GitHub.