nautechsystems/nautilus_trader · error

Execution payload storage is in {operation} maintenance, not

Error message

Execution payload storage is in {operation} maintenance, not ready for rewrap

What it means

begin_execution_payload_rewrap starts a key-rotation (rewrap) of sealed execution payloads. It accepts state.operation of 'ready' (start a new rewrap) or 'rewrap' (resume), but any other maintenance operation — such as 'migrate' or 'rollback' — means storage is mid-transition and cannot begin a rewrap. The library bails to prevent overlapping maintenance operations corrupting payload protection state.

Source

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

                if current_id == *keys.active_key_id() {
                    transaction
                        .commit()
                        .await
                        .context("failed to complete no-op execution payload rewrap")?;
                    return Ok(());
                }
                sqlx::query(
                    "UPDATE execution_payload_state \
                     SET operation = 'rewrap', active_key_id = $1, progress_id = 0, updated_at = NOW() \
                     WHERE component = 'signed_transactions'",
                )
                .bind(keys.active_key_id().as_slice())
                .execute(&mut *transaction)
                .await
                .context("failed to record execution payload rewrap target")?;
            }
            "rewrap" => validate_execution_payload_state(&state, keys)?,
            operation => anyhow::bail!(
                "Execution payload storage is in {operation} maintenance, not ready for rewrap"
            ),
        }
        sqlx::query(
            "INSERT INTO execution_payload_key_state (key_id, seals) VALUES ($1, 0) \
             ON CONFLICT (key_id) DO NOTHING",
        )
        .bind(keys.active_key_id().as_slice())
        .execute(&mut *transaction)
        .await
        .context("failed to initialize rewrap target key state")?;
        transaction
            .commit()
            .await
            .context("failed to commit execution payload rewrap state")?;
        Ok(())
    }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Wait for / complete the current maintenance operation ('migrate' batches until ready, or finish 'rollback') before starting the rewrap
  2. If a rollback is intended to supersede rotation, cancel the rewrap attempt instead of forcing it
  3. Inspect execution_payload_state.operation to confirm current phase and re-run the rewrap command once it reads 'ready'
  4. Serialize maintenance tasks so only one rotation/migration/rollback runs at a time

Example fix

// before: rewrap attempted during unfinished migration
begin_execution_payload_rewrap(&keys).await?;
// after: run migration to completion first
while !migrate_execution_payload_batch(&keys, BATCH).await? {}
begin_execution_payload_rewrap(&keys).await?;
Defensive patterns

Strategy: validation

Validate before calling

let op: String = sqlx::query_scalar(
    "SELECT operation FROM execution_payload_state WHERE component = 'signed_transactions'")
    .fetch_one(&pool).await?;
anyhow::ensure!(matches!(op.as_str(), "ready" | "rewrap"),
    "cannot rewrap while storage operation is '{op}'");

Type guard

fn rewrap_allowed(operation: &str) -> bool {
    matches!(operation, "ready" | "rewrap")
}

Try / catch

match db.begin_execution_payload_rewrap(&keys).await {
    Err(e) if e.to_string().contains("not ready for rewrap") => {
        // finish current migrate/rollback, then retry rewrap
    }
    r => r?,
}

Prevention

When it happens

Trigger: Invoking the rewrap command (begin_execution_payload_rewrap) while execution_payload_state.operation is 'migrate' or 'rollback' — e.g. initial encryption migration not yet finished, or a previous rollback in progress, and an operator attempts to rotate keys on top of it.

Common situations: Operator skipped the initial migration step and ran key rotation immediately; concurrent maintenance jobs on the same database; an unfinished rollback from a downgrade attempt still recorded in the state table; automation schedules colliding.

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/227af283e5a88cd9. Report an issue: GitHub.