nautechsystems/nautilus_trader · error
Replacement scan conflicts with the durable finalized header
Error message
Replacement scan conflicts with the durable finalized header ledger
What it means
After the replacement scan, the scanned tip must match the durable finalized header cursor stored in the database (if one exists for this intent/nonce/manifest). A mismatch means the in-memory scan result contradicts the persisted finalized ledger — the local scan and durable history have diverged.
Source
Thrown at crates/adapters/blockchain/src/execution/client.rs:3143
});
let candidate = candidates.next();
anyhow::ensure!(
candidates.next().is_none(),
"Canonical replacement scan found duplicate signer-nonce transactions"
);
let finalized_cursor = self
.database
.load_execution_verified_header(
self.chain_id,
&wallet_address,
end,
&self.manifest_digest,
)
.await?;
if let Some(cursor) = finalized_cursor.as_ref() {
anyhow::ensure!(
parse_verified_header(cursor)? == scanned_tip,
"Replacement scan conflicts with the durable finalized header ledger"
);
}
let mut mismatch = None;
let matched = candidate.and_then(|transaction| {
let Some(raw_transaction) = authenticated_payloads.get(&transaction.hash).cloned()
else {
mismatch = Some(anyhow::anyhow!(
"Canonical signer-nonce transaction {} has no authenticated retained payload",
transaction.hash
));
return None;
};
if let Err(e) = validate_rpc_transaction_matches_payload(transaction, &raw_transaction)
{View on GitHub (pinned to 18893faf8b)
Solutions
- Confirm chain_id, wallet, and manifest_digest in the client config match those the ledger cursor was written with
- Inspect the execution_replacement_cursor row and compare its header with the chain; reorg-aware repair or reset the cursor
- Re-run reconciliation from an earlier block so the ledger is rebuilt consistently
- Verify no out-of-band process mutates the ledger concurrently
Defensive patterns
Strategy: validation
Validate before calling
let cursor = db.load_execution_replacement_cursor(intent.id, chain_id, wallet, nonce, manifest_digest).await?;
if let Some(cur) = cursor {
if parse_verified_header(&cur)? != scanned_tip {
return Err("ledger cursor and scan diverged; repair before proceeding");
}
} Prevention
- Keep chain_id/manifest_digest consistent across restarts
- Detect reorgs before trusting finalized cursors
- Restrict DB writes to the client process
- Cross-check cursor headers against the chain at startup
When it happens
Trigger: load_execution_replacement_cursor returned a finalized cursor whose parsed header differs from the scanned tip — e.g. the database cursor was written against a different chain/manifest, or a reorg invalidated previously finalized data while the DB retains the old header.
Common situations: Reusing a database across chain environments; reorg after the cursor was persisted; manually edited or migrated DB rows; pointing the client at a different RPC after the ledger was built.
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
- Verified finalized header ledger is not continuous
- Verified finalized transaction count advanced without an act
- Verified finalized transaction count is outside the owned re
- Verified finalized header extension does not start at the du
- Finalized header ledger conflicts at height {}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/06a54ce34640f11f.
Report an issue: GitHub.