{"record":{"id":"6003bb5bc5628a9e","repo":"nautechsystems/nautilus_trader","slug":"canonical-replacement-scan-found-duplicate-signer","errorCode":null,"errorMessage":"Canonical replacement scan found duplicate signer-nonce transactions","messagePattern":"Canonical replacement scan found duplicate signer-nonce transactions","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":3127,"sourceCode":"\n        let scanned_tip = blocks\n            .last()\n            .map(|block| VerifiedBlockHeader::from(block.clone()))\n            .ok_or_else(|| anyhow::anyhow!(\"Verified replacement scan returned no blocks\"))?;\n        if end == head.number {\n            anyhow::ensure!(\n                scanned_tip == head,\n                \"Replacement scan tip conflicts with the verified canonical head\"\n            );\n        }\n        let mut candidates = blocks\n            .iter()\n            .flat_map(|block| block.transactions.iter())\n            .filter(|transaction| {\n                transaction.from == self.wallet_address && transaction.nonce == nonce\n            });\n        let candidate = candidates.next();\n        anyhow::ensure!(\n            candidates.next().is_none(),\n            \"Canonical replacement scan found duplicate signer-nonce transactions\"\n        );\n\n        let finalized_cursor = self\n            .database\n            .load_execution_verified_header(\n                self.chain_id,\n                &wallet_address,\n                end,\n                &self.manifest_digest,\n            )\n            .await?;\n\n        if let Some(cursor) = finalized_cursor.as_ref() {\n            anyhow::ensure!(\n                parse_verified_header(cursor)? == scanned_tip,\n                \"Replacement scan conflicts with the durable finalized header ledger\"","sourceCodeStart":3109,"sourceCodeEnd":3145,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/execution/client.rs#L3109-L3145","documentation":"While scanning canonical blocks for a transaction with the wallet's signer nonce, the client expects at most one transaction matching (from == wallet, nonce == N). Finding two or more means the scanned history contains duplicate signer-nonce transactions, which is impossible on a valid canonical chain and indicates corrupted or cross-branch data.","triggerScenarios":"The concatenated replacement-scan blocks contained multiple transactions from self.wallet_address with the same nonce — e.g. overlapping block windows concatenated twice, the cursor produced overlapping ranges, or an untrusted provider returned duplicate/malformed block payloads.","commonSituations":"Bug or corruption in block-window assembly (start block plus window overlapping); malicious or misconfigured RPC returning fabricated transactions; mixing data from two providers.","solutions":["Check that the start block and the follow-up window do not overlap (window should start at start+1)","Verify the provider is trusted and returns canonical history; cross-check one block's transactions against a second source","Clear the replacement cursor and rescan from intent.created_block","Audit the manifest_digest/chain configuration for mixing environments"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let mut matches = blocks.iter()\n    .flat_map(|b| b.transactions.iter())\n    .filter(|tx| tx.from == wallet && tx.nonce == nonce);\nlet first = matches.next();\nif matches.next().is_some() {\n    return Err(\"duplicate signer-nonce txs; block windows overlap or provider untrusted\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure scan windows are disjoint (window starts at start+1)","Use only trusted, verified data sources","Reset cursors to avoid overlapping rescans","Never mix block data from multiple providers in one scan"],"tags":["blockchain","nonce","duplicate","data-integrity"],"backgroundTag":"internal-invariant-violation","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}