{"record":{"id":"5e03f92a773ca217","repo":"nautechsystems/nautilus_trader","slug":"protected-payload-keys-are-required-for-execution","errorCode":null,"errorMessage":"Protected payload keys are required for execution recovery","messagePattern":"Protected payload keys are required for execution recovery","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":1130,"sourceCode":"            weth: self.weth_address,\n            token_in,\n            token_out,\n            fee,\n            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,","sourceCodeStart":1112,"sourceCodeEnd":1148,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/execution/client.rs#L1112-L1148","documentation":"reconcile_unresolved_execution acquires an execution payload lease that protects specific payload keys (self.payload_keys) from concurrent modification during recovery. If payload_keys is not configured (None), the client cannot establish the lease and aborts connect. The library throws this because concurrent recovery without key protection could double-drive the same signed payloads.","triggerScenarios":"connect() -> reconcile_unresolved_execution calls database.acquire_execution_payload_lease(self.payload_keys.as_deref()...) while self.payload_keys is None or empty. Occurs when the execution client is constructed without its protected payload keys configuration (e.g. keys for signed transaction payloads) yet durable reconciliation is enabled.","commonSituations":"Partial configuration of the blockchain execution client: database configured but payload-keys option omitted; building the client programmatically and skipping the payload_keys field; version/config drift where a new required option was added but not set in existing configs.","solutions":["Set the payload_keys configuration on the blockchain execution client to the keys protecting its execution payloads, then reconnect.","Check adapter docs/config schema for the payload-keys (protected payload) option and supply the values used by your deployment.","If constructing the client in code, populate the payload_keys field of the client's config/args instead of leaving it None.","If this appears after an upgrade, diff your config against the new required fields and add the missing payload-keys entry."],"exampleFix":"// before\nExecutionClientConfig(database=..., )  # payload_keys missing\n// after\nExecutionClientConfig(database=..., payload_keys=[\"execution:signed_tx:0xWallet\"])","handlingStrategy":"validation","validationCode":"// Before connect, verify payload keys are configured\nif config.payload_keys.as_deref().unwrap_or(&[]).is_empty() {\n    panic!(\"payload_keys must be set for execution recovery\");\n}","typeGuard":"fn has_payload_keys(keys: &Option<Vec<String>>) -> bool {\n    keys.as_ref().map(|k| !k.is_empty()).unwrap_or(false)\n}","tryCatchPattern":null,"preventionTips":["Set payload_keys whenever the durable store is enabled for the blockchain execution client","Diff configs against the adapter's required fields after upgrades","Populate payload_keys in programmatic client construction, not just YAML","Document the pairing database<->payload_keys so one is never set without the other"],"tags":["persistence","missing-config","reconciliation","locking"],"backgroundTag":"missing-required-config-field","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"}