nautechsystems/nautilus_trader · critical · anyhow::Error

Execution verification manifest identity changed

Error message

Execution verification manifest identity changed

What it means

Raised in database.rs:3712 when the persisted verification nonce row's manifest_version or manifest_digest do not match the digest/version of the manifest the caller is using. The manifest is the identity of the verification rules and contract set; a mismatch means the stored verification state was produced under a different manifest and is not interchangeable with the current one.

Source

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

        );
        let chain_id =
            i32::try_from(chain_id).context("Verification chain ID exceeds PostgreSQL INTEGER")?;
        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
            ",
        )
        .bind(chain_id)
        .bind(wallet_address)
        .fetch_optional(&self.pool)
        .await
        .context("failed to load execution verification nonce position")?;
        let Some((stored_version, stored_digest, nonce, revision)) = current else {
            return Ok(None);
        };
        anyhow::ensure!(
            stored_version == manifest_version && stored_digest == manifest_digest,
            "Execution verification manifest identity changed"
        );
        let row = sqlx::query_as::<_, (i64, String, String, i64, Option<String>, String)>(
            "
            SELECT number, hash, parent_hash, timestamp, base_fee_per_gas, manifest_digest
            FROM execution_verified_finalized_header
            WHERE chain_id = $1 AND wallet_address = $2
            ORDER BY number DESC
            LIMIT 1
            ",
        )
        .bind(chain_id)
        .bind(wallet_address)
        .fetch_optional(&self.pool)
        .await
        .context("failed to load verified finalized header tip")?
        .ok_or_else(|| anyhow::anyhow!("Verified finalized header ledger is empty"))?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Re-bootstrap the verification state for this wallet/chain so the stored manifest matches the current one.
  2. Verify the manifest version and digest your deployment passes match the values used when the database was initialized.
  3. If the manifest change was accidental, revert the manifest configuration to the digest stored in execution_verification_nonce.
  4. Wipe/rotate verification state for the affected wallet deliberately (with the prior nonce accounted for) rather than editing rows ad hoc.

Example fix

// before: manifest config edited -> digest mismatch
let pos = db.load_execution_verification_position(chain, wallet, "v1", &old_digest).await;
// after: pass the manifest identity that matches the stored state, or re-bootstrap
let (ver, digest) = current_manifest_identity();
assert_eq!((ver, digest), stored_manifest_identity(&db, chain, wallet)?);
let pos = db.load_execution_verification_position(chain, wallet, &ver, &digest).await?;
Defensive patterns

Strategy: validation

Validate before calling

let stored: Option<(String, String)> = sqlx::query_as(
    "SELECT manifest_version, manifest_digest FROM execution_verification_nonce \
     WHERE chain_id = $1 AND wallet_address = $2",
).bind(chain_id).bind(wallet).fetch_optional(&pool).await?;
if let Some((v, d)) = stored {
    assert_eq!((v.as_str(), d.as_str()), (manifest_version, manifest_digest),
        "manifest identity drifted; re-bootstrap required");
}

Try / catch

match load_position(...).await {
    Err(e) if e.to_string().contains("manifest identity changed") => {
        // halt verification for this wallet; re-bootstrap under the new manifest
    },
    other => other?,
}

Prevention

When it happens

Trigger: Calling load_execution_verification_position with manifest_version/manifest_digest arguments that differ from the (manifest_version, manifest_digest) stored in execution_verification_nonce for the given chain_id and wallet_address.

Common situations: Changing the verification manifest (adding/changing verified contracts or rules) without re-bootstrapping the wallet's verification state; pointing the node at a database initialized for a different deployment configuration; wallet previously verified under a different manifest revision.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


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