{"record":{"id":"c645ba379a13a721","repo":"nautechsystems/nautilus_trader","slug":"disconnect-the-execution-client-before-payload-sto","errorCode":null,"errorMessage":"Disconnect the execution client before payload storage operations","messagePattern":"Disconnect the execution client before payload storage operations","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/blockchain/src/execution/client.rs","lineNumber":926,"sourceCode":"    /// succeeds and the unprotected database passes a full payload check.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the client is connected, storage is not protected, required keys are\n    /// unavailable, or any bounded rollback batch fails authentication.\n    pub async fn rollback_payload_storage(&self, batch_size: usize) -> anyhow::Result<()> {\n        let batch_size = validate_payload_operation_batch_size(batch_size)?;\n        let database = self.payload_operation_database().await?;\n        let keys = self\n            .load_payload_keys()?\n            .ok_or_else(|| anyhow::anyhow!(\"Payload rollback requires an active payload key\"))?;\n        database\n            .rollback_execution_payload_storage(&keys, batch_size)\n            .await\n    }\n\n    async fn payload_operation_database(&self) -> anyhow::Result<BlockchainCacheDatabase> {\n        anyhow::ensure!(\n            !self.core.is_connected(),\n            \"Disconnect the execution client before payload storage operations\"\n        );\n\n        if let Some(database) = &self.cache.database {\n            return Ok(database.clone());\n        }\n        let options = self\n            .config\n            .postgres_cache_database_config\n            .as_ref()\n            .ok_or_else(|| anyhow::anyhow!(\"No Postgres cache database is configured\"))?;\n        BlockchainCacheDatabase::connect(options.clone().into())\n            .await\n            .context(\"failed to connect to the execution database\")\n    }\n\n    fn load_payload_keys(&self) -> anyhow::Result<Option<PayloadKeySet>> {","sourceCodeStart":908,"sourceCodeEnd":944,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/blockchain/src/execution/client.rs#L908-L944","documentation":"payload_operation_database() is the shared entry point for all payload storage maintenance operations (check/protect/rewrap/rollback). It enforces via anyhow::ensure! that the execution client is NOT connected, because these operations mutate the storage directly and concurrent use by a live client would race or corrupt data. If self.core.is_connected() is true, the operation is rejected.","triggerScenarios":"Calling check_payload_storage, protect_payload_storage, rewrap_payload_storage, or rollback_payload_storage while the execution client still holds an active connection.","commonSituations":"Maintenance scripts that connect the client first (to check health) and then immediately try protect/rewrap; long-lived live trading clients where an operator runs payload maintenance without disconnecting.","solutions":["Call client.disconnect() (or equivalent shutdown) before invoking any payload storage operation.","Run payload maintenance in a separate process/mode where the client is constructed without connecting.","Reconnect the client after the operation completes if continued trading is needed."],"exampleFix":"// before\nclient.protect_payload_storage(1000).await?;\n// after\nclient.disconnect().await?;\nclient.protect_payload_storage(1000).await?;\nclient.connect().await?;","handlingStrategy":"validation","validationCode":"anyhow::ensure!(!client.is_connected(), \"disconnect the client before payload maintenance\");\nclient.rewrap_payload_storage(batch_size).await?;","typeGuard":null,"tryCatchPattern":"match client.protect_payload_storage(batch).await {\n    Ok(()) => client.connect().await?,\n    Err(e) if e.to_string().contains(\"Disconnect the execution client\") => {\n        client.disconnect().await?;\n        client.protect_payload_storage(batch).await?;\n        client.connect().await?;\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Run payload maintenance in a dedicated maintenance mode/process.","Always disconnect before check/protect/rewrap/rollback.","Automate: disconnect -> operate -> reconnect in one script."],"tags":["rust","payload-storage","invalid-state","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"}