{"record":{"id":"b2c13e753fd40871","repo":"nautechsystems/nautilus_trader","slug":"pending-nonce-does-not-match-the-verified-canonica","errorCode":null,"errorMessage":"Pending nonce does not match the verified canonical nonce","messagePattern":"Pending nonce does not match the verified canonical nonce","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":2428,"sourceCode":"        if let Some(anchors) = swap_anchors {\n            decisions.extend(self.verify_swap_anchors_before_sign(anchors).await?);\n            decisions.extend(anchors.precondition_decisions.iter().cloned());\n        } else {\n            decisions.extend(self.verify_pre_sign_header_fence(decision_header).await?);\n        }\n        let canonical_nonce_verification = required_verification(\n            self.verification\n                .verify_transaction_count(&self.wallet_address, decision_header.number)\n                .await,\n            \"pre-sign canonical nonce reread\",\n        )?;\n        let pending_nonce_verification = required_verification(\n            self.verification\n                .verify_pending_transaction_count(&self.wallet_address)\n                .await,\n            \"pre-sign pending nonce reread\",\n        )?;\n        anyhow::ensure!(\n            pending_nonce_verification.value == canonical_nonce_verification.value,\n            \"Pending nonce does not match the verified canonical nonce\"\n        );\n        let nonce = canonical_nonce_verification.value;\n        decisions.push(verification_decision(\n            &canonical_nonce_verification,\n            decision_height,\n            decision_height,\n        ));\n        decisions.push(verification_decision(\n            &pending_nonce_verification,\n            None,\n            None,\n        ));\n        let tx = build_eip1559_transaction(\n            expected_chain_id,\n            nonce,\n            gas_limit,","sourceCodeStart":2410,"sourceCodeEnd":2446,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/execution/client.rs#L2410-L2446","documentation":"Before signing, the client reads the account nonce twice: the canonical nonce at the verified decision block and the pending (mempool-inclusive) transaction count. Signing is only safe when they match — i.e. the wallet has no in-flight transactions. A mismatch means pending transactions exist that would collide with the nonce about to be assigned, so the client aborts.","triggerScenarios":"Calling the pre-sign path while the wallet has unconfirmed transactions in the mempool (pending nonce > canonical nonce), or a stale/inconsistent RPC where the pending view lags or diverges from the canonical view.","commonSituations":"A previous broadcast is still unconfirmed (stuck/slow transaction); another process or bot shares the same wallet key and broadcast concurrently; RPC provider returning inconsistent pending vs latest state; retry loop re-signing before confirmation of the earlier tx.","solutions":["Wait for the pending transaction(s) to be confirmed (or explicitly replace/cancel them with a higher-priority-fee same-nonce transaction), then retry.","Ensure a single signing process owns the wallet; add cross-process nonce leasing/locking.","Retry after the mempool clears; the check is designed to be re-run and will pass once pending == canonical.","Point the client at a consistent, in-sync RPC endpoint; avoid load-balanced providers with divergent nodes."],"exampleFix":"// before: immediate retry after broadcast, pending tx still in flight\nlet prepared = client.prepare_and_sign(intent).await?; // fails: pending nonce 7 != canonical 6\n// after: confirm the previous tx first\nwait_for_confirmation(previous_tx_hash).await?;\nlet prepared = client.prepare_and_sign(intent).await?;","handlingStrategy":"retry","validationCode":"pub async fn nonce_clear(ver: &Verification, wallet: Address) -> anyhow::Result<bool> {\n    let canonical = ver.verify_transaction_count(&wallet, latest()).await?;\n    let pending = ver.verify_pending_transaction_count(&wallet).await?;\n    Ok(pending.value == canonical.value)\n}","typeGuard":null,"tryCatchPattern":"match sign_attempt().await {\n    Err(e) if e.to_string().contains(\"Pending nonce does not match\") => {\n        wait_for_pending_confirmation().await?;\n        sign_attempt().await?\n    }\n    other => other?,\n}","preventionTips":["Ensure exactly one signing process owns the wallet key; use nonce leasing.","Wait for confirmation of a broadcast before preparing the next transaction.","Use a consistent, in-sync RPC endpoint for both canonical and pending reads."],"tags":["blockchain","nonce","mempool","concurrency"],"backgroundTag":"invalid-state-transition","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"}