{"record":{"id":"80a4c2c621cc63fd","repo":"nautechsystems/nautilus_trader","slug":"a-recoverable-execution-for-wallet-retains-sign","errorCode":null,"errorMessage":"A recoverable execution for wallet {} retains signed transaction bytes; refusing to reuse its nonce without explicit recovery","messagePattern":"A recoverable execution for wallet (.+?) retains signed transaction bytes; refusing to reuse its nonce without explicit recovery","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":1134,"sourceCode":"            amount_in,\n            min_amount_out: U256::ZERO,\n            slippage_bps: 0,\n            quote_spend_ceiling: None,\n            profiler_position: None,\n        })\n    }\n\n    async fn reconcile_unresolved_execution(&self) -> anyhow::Result<()> {\n        let database = self.cache.database.clone().ok_or_else(|| {\n            anyhow::anyhow!(\"No durable store configured for execution reconciliation\")\n        })?;\n        let _payload_lease = database\n            .acquire_execution_payload_lease(self.payload_keys.as_deref().ok_or_else(|| {\n                anyhow::anyhow!(\"Protected payload keys are required for execution recovery\")\n            })?)\n            .await?;\n        let wallet_address = self.wallet_address.to_string();\n        anyhow::ensure!(\n            !database\n                .has_recoverable_signed_execution(self.chain.chain_id, &wallet_address)\n                .await?,\n            \"A recoverable execution for wallet {} retains signed transaction bytes; refusing to reuse its nonce without explicit recovery\",\n            self.wallet_address\n        );\n        let Some(intent) = database\n            .get_active_execution_intent(self.chain.chain_id, &wallet_address)\n            .await?\n        else {\n            return Ok(());\n        };\n        anyhow::ensure!(\n            intent.schema_version == crate::execution::transaction::EXECUTION_SCHEMA_VERSION,\n            \"Execution intent {} uses unsupported schema version {}\",\n            intent.id,\n            intent.schema_version\n        );","sourceCodeStart":1116,"sourceCodeEnd":1152,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/execution/client.rs#L1116-L1152","documentation":"During startup reconciliation, the client refuses to acquire a nonce when the database still holds a recoverable execution containing signed transaction bytes for this wallet. Reusing the nonce could broadcast a second transaction with the same nonce, so recovery must be explicit. This is a safety interlock against double-spend / nonce-collision from an interrupted broadcast.","triggerScenarios":"connect() calls reconcile_unresolved_execution(); database.has_recoverable_signed_execution(chain_id, wallet) returns true because a previous run persisted signed tx bytes (raw/sealed transaction) for a wallet before crashing or being killed mid-broadcast.","commonSituations":"Process killed after signing but before confirming broadcast; crash during deployment; running a second instance against the same wallet/database; stale recovery rows left after an aborted run.","solutions":["Run the explicit recovery flow (recovery path of reconcile_unresolved_execution / recovery tooling) to replay or discard the stored signed execution before reconnecting","Clear the recoverable signed execution rows for this wallet in the execution database once the transaction's on-chain status is confirmed","Ensure only one client instance uses this wallet/keystore at a time and that previous runs shut down cleanly","Restore the payload keys (payload_keys config) so recovery can proceed instead of failing earlier"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before connect(), check recovery state\nlet has_recoverable = database.has_recoverable_signed_execution(chain.chain_id, &wallet_address).await?;\nif has_recoverable {\n    // run explicit recovery or clean the rows first\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run the recovery flow promptly after any crash instead of restarting blind","Ensure only one process owns a wallet's nonce at a time","Persist signed bytes and clear them atomically with broadcast confirmation"],"tags":["blockchain","nonce","recovery","startup"],"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"}