{"record":{"id":"0432cb92b7d101f3","repo":"nautechsystems/nautilus_trader","slug":"finalized-checkpoint-ledger-conflicts-with-the-tru","errorCode":null,"errorMessage":"Finalized checkpoint ledger conflicts with the trusted chain anchor","messagePattern":"Finalized checkpoint ledger conflicts with the trusted chain anchor","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"critical","filePath":"crates/adapters/blockchain/src/cache/database.rs","lineNumber":4404,"sourceCode":"        .bind(base_fee)\n        .bind(bootstrap.manifest_digest)\n        .execute(&mut *transaction)\n        .await\n        .map_err(|e| anyhow::anyhow!(\"Failed to initialize finalized header ledger: {e}\"))?;\n        let stored_checkpoint = sqlx::query_as::<_, (String, String, i64, Option<String>)>(\n            \"\n            SELECT hash, parent_hash, timestamp, base_fee_per_gas\n            FROM execution_verified_finalized_header\n            WHERE chain_id = $1 AND wallet_address = $2 AND number = $3\n            \",\n        )\n        .bind(chain_id)\n        .bind(bootstrap.wallet_address)\n        .bind(checkpoint_number)\n        .fetch_one(&mut *transaction)\n        .await\n        .map_err(|e| anyhow::anyhow!(\"Failed to validate finalized checkpoint ledger: {e}\"))?;\n        anyhow::ensure!(\n            stored_checkpoint\n                == (\n                    bootstrap.checkpoint_hash.to_string(),\n                    bootstrap.checkpoint_parent_hash.to_string(),\n                    checkpoint_timestamp,\n                    bootstrap\n                        .checkpoint_base_fee_per_gas\n                        .map(|value| value.to_string()),\n                ),\n            \"Finalized checkpoint ledger conflicts with the trusted chain anchor\"\n        );\n\n        if initialized {\n            let stored_tip =\n                sqlx::query_as::<_, (i64, String, String, i64, Option<String>, String)>(\n                    \"\n                SELECT number, hash, parent_hash, timestamp, base_fee_per_gas, manifest_digest\n                FROM execution_verified_finalized_header","sourceCodeStart":4386,"sourceCodeEnd":4422,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/cache/database.rs#L4386-L4422","documentation":"This is an integrity violation raised by anyhow::ensure! after comparing the stored checkpoint row against the trusted bootstrap anchor. If the durable row's (hash, parent_hash, timestamp, base_fee_per_gas) tuple does not exactly equal the trusted checkpoint supplied in the bootstrap payload, the library refuses to proceed: the local ledger's chain anchor disagrees with the expected chain, which would silently fork or corrupt verification state.","triggerScenarios":"Bootstrapping a wallet/chain whose stored checkpoint at `checkpoint_number` was written from a different chain (e.g. testnet data in a mainnet database), a reorged or different checkpoint supplied in bootstrap config, or manual tampering/repair of the ledger table.","commonSituations":"Pointing the adapter at a database previously used with a different network or chain_id/wallet; changing the trusted checkpoint configuration after initialization; a bad snapshot/restore leaving rows from another deployment; hand-edited rows.","solutions":["Verify the bootstrap checkpoint (checkpoint_hash, checkpoint_parent_hash, timestamp, base_fee) matches the actual chain — recompute from a trusted beacon/execution source.","Check chain_id and wallet_address in your configuration; the ledger keys on (chain_id, wallet_address, number) and mixing environments causes collisions.","Inspect the existing row: SELECT * FROM execution_verified_finalized_header WHERE chain_id=$1 AND wallet_address=$2 AND number=$3; if it is from stale/wrong data, move it to a new database or purge that wallet's ledger rows deliberately and re-bootstrap.","Do not manually edit rows to make the comparison pass — that defeats the integrity check."],"exampleFix":"// before — mismatch surfaces only at runtime\nanyhow::ensure!(\n    stored_checkpoint == (bootstrap.checkpoint_hash.to_string(), /* ... */),\n    \"Finalized checkpoint ledger conflicts with the trusted chain anchor\"\n);\n\n// after — validate the anchor before opening the write transaction\nlet existing: Option<(String, String, i64, Option<String>)> = sqlx::query_as(/* SELECT ... */)\n    .bind(chain_id)\n    .bind(bootstrap.wallet_address)\n    .bind(bootstrap.checkpoint_number)\n    .fetch_optional(&mut *transaction)\n    .await?;\nif let Some(row) = existing {\n    anyhow::ensure!(\n        row.0 == bootstrap.checkpoint_hash.to_string(),\n        \"Checkpoint {} for chain {chain_id} is {} but bootstrap anchor is {} — use a fresh database or the matching chain config\",\n        bootstrap.checkpoint_number, row.0, bootstrap.checkpoint_hash\n    );\n}","handlingStrategy":"validation","validationCode":"// Validate the anchor against the DB BEFORE the bootstrap write path\nlet existing: Option<(String,)> = sqlx::query_as(\n    \"SELECT hash FROM execution_verified_finalized_header WHERE chain_id=$1 AND wallet_address=$2 AND number=$3\",\n).bind(chain_id).bind(wallet).bind(checkpoint_number).fetch_optional(&pool).await?;\nif let Some((hash,)) = existing {\n    anyhow::ensure!(\n        hash == expected_checkpoint_hash,\n        \"DB checkpoint {checkpoint_number} is {hash}, config anchor is {expected_checkpoint_hash} — align chain config or use a fresh database\"\n    );\n}","typeGuard":"fn matches_trusted_anchor(stored: &(String, String, i64, Option<String>), b: &Bootstrap) -> bool {\n    stored.0 == b.checkpoint_hash.to_string()\n        && stored.1 == b.checkpoint_parent_hash.to_string()\n        && stored.3.as_deref() == b.checkpoint_base_fee_per_gas.map(|v| v.to_string()).as_deref()\n}","tryCatchPattern":"match bootstrap_result {\n    Err(e) if e.to_string().contains(\"conflicts with the trusted chain anchor\") => {\n        error!(\"Ledger anchored to a different chain — verify chain_id/network config, do NOT edit rows to force a match\");\n        std::process::exit(1);\n    }\n    other => other,\n}","preventionTips":["Key each environment (mainnet/testnet/dev) on a separate database so chain data never mixes","Never change the trusted checkpoint hash/timestamp after a ledger is initialized","Never hand-edit ledger rows to satisfy the comparison","Verify the bootstrap checkpoint against a trusted beacon source before configuring it"],"tags":["integrity","blockchain","consistency","checkpoint"],"backgroundTag":"checksum-mismatch","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}