nautechsystems/nautilus_trader · error · anyhow::Error

Verification migration was supplied for an initialized signe

Error message

Verification migration was supplied for an initialized signer

What it means

The nonce ledger already has an initialized row for this (chain_id, wallet_address), meaning the signer has been bootstrapped before. A migration payload in the bootstrap request would re-initialize or transform signer state, which is only legal for a fresh/uninitialized signer, so the code rejects it to protect the existing durable nonce history.

Source

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

        let current = sqlx::query_as::<_, (String, String, i64, i64)>(
            "
            SELECT manifest_version, manifest_digest, next_canonical_nonce, revision
            FROM execution_verification_nonce
            WHERE chain_id = $1 AND wallet_address = $2
            FOR UPDATE
            ",
        )
        .bind(chain_id)
        .bind(bootstrap.wallet_address)
        .fetch_optional(&mut *transaction)
        .await
        .map_err(|e| anyhow::anyhow!("Failed to read canonical nonce ledger: {e}"))?;
        let initialized = current.is_some();

        let revision = if let Some((manifest_version, manifest_digest, stored_nonce, revision)) =
            current
        {
            anyhow::ensure!(
                bootstrap.migration.is_none(),
                "Verification migration was supplied for an initialized signer"
            );
            anyhow::ensure!(
                manifest_version == bootstrap.manifest_version
                    && manifest_digest == bootstrap.manifest_digest,
                "Execution verification manifest identity changed"
            );
            anyhow::ensure!(
                stored_nonce == next_canonical_nonce,
                "Canonical nonce ledger changed during verification bootstrap"
            );

            if observed_canonical_nonce != stored_nonce {
                let expected_observed_nonce = stored_nonce
                    .checked_add(1)
                    .ok_or_else(|| anyhow::anyhow!("Canonical nonce overflow"))?;
                anyhow::ensure!(

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Remove the migration parameter from the bootstrap request for this wallet — it is already initialized
  2. Use a fresh wallet_address if a migration-backed initialization is truly intended
  3. Verify chain_id/wallet_address match the intended signer; a typo can make an initialized signer appear at the wrong key
  4. If state is genuinely corrupted, follow the project's documented recovery procedure rather than re-migrating

Example fix

// before
let bootstrap = Bootstrap { manifest_version, manifest_digest, migration: Some(mig), .. };
// after (wallet already initialized)
let bootstrap = Bootstrap { manifest_version, manifest_digest, migration: None, .. };
Defensive patterns

Strategy: validation

Validate before calling

// Only include a migration when the signer row is absent
let initialized = sqlx::query_scalar::<_, i32>(
  "SELECT 1 FROM execution_verification_nonce
   WHERE chain_id=$1 AND wallet_address=$2")
  .bind(chain_id).bind(wallet)
  .fetch_optional(&mut *conn).await?.is_some();
let migration_opt = if initialized { None } else { Some(migration) };

Try / catch

match bootstrap_signer(req).await {
    Err(e) if e.to_string().contains("Verification migration was supplied for an initialized signer") => {
        warn!(wallet = %req.wallet, "already initialized; dropping migration and retrying");
        bootstrap_signer(Bootstrap { migration: None, ..req }).await
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling the verification bootstrap with bootstrap.migration = Some(..) for a chain_id/wallet_address whose execution_verification_nonce row already exists.

Common situations: Re-running an initial-setup script (that includes a migration parameter) against an already-initialized signer; copy-pasting a bootstrap config from a new wallet to an existing one; pointing a migration job at production after it ran in staging with the same wallet.

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/3df1a3143f395730. Report an issue: GitHub.