{"record":{"id":"e360439a8a2f3eed","repo":"nautechsystems/nautilus_trader","slug":"failed-to-disconnect-data-clients","errorCode":null,"errorMessage":"Failed to disconnect data clients: {}","messagePattern":"Failed to disconnect data clients: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/data/src/engine/mod.rs","lineNumber":776,"sourceCode":"    ///\n    /// # Errors\n    ///\n    /// Returns an error if any client fails to disconnect.\n    pub async fn disconnect(&mut self) -> anyhow::Result<()> {\n        let futures: Vec<_> = self\n            .get_clients_mut()\n            .into_iter()\n            .map(DataClientAdapter::disconnect)\n            .collect();\n\n        let results = join_all(futures).await;\n        let errors: Vec<_> = results.into_iter().filter_map(Result::err).collect();\n\n        if errors.is_empty() {\n            Ok(())\n        } else {\n            let error_msgs: Vec<_> = errors.iter().map(ToString::to_string).collect();\n            anyhow::bail!(\n                \"Failed to disconnect data clients: {}\",\n                error_msgs.join(\"; \")\n            )\n        }\n    }\n\n    /// Returns `true` if all registered data clients are currently connected.\n    #[must_use]\n    pub fn check_connected(&self) -> bool {\n        self.get_clients()\n            .iter()\n            .all(|client| client.is_connected())\n    }\n\n    /// Returns `true` if all registered data clients are currently disconnected.\n    #[must_use]\n    pub fn check_disconnected(&self) -> bool {\n        self.get_clients()","sourceCodeStart":758,"sourceCodeEnd":794,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/data/src/engine/mod.rs#L758-L794","documentation":"The engine's disconnect method sends disconnect commands to all registered data clients and collects per-client errors. If any client failed to disconnect, it aggregates all error messages (joined with \"; \") into a single error. This is a wrapper error — the real causes are in the inner per-client messages.","triggerScenarios":"Calling DataEngine::disconnect() when one or more underlying data clients return Err from their disconnect (network failures, adapter-side disconnect errors, clients already in a bad state).","commonSituations":"Shutting down a node where a websocket/adapter connection is already broken; adapter disconnect RPC timing out; multiple adapter failures during teardown causing a long joined error string.","solutions":["Parse the joined message after \"Failed to disconnect data clients: \" and split on \"; \" to identify which clients failed.","Fix the root cause per client (check network connectivity, adapter logs, and that clients were connected before disconnect).","Make disconnect idempotent/tolerant in your shutdown path: log the aggregate error and continue teardown rather than aborting."],"exampleFix":"// before\nengine.disconnect()?; // aborts whole shutdown on one bad client\n// after\nif let Err(e) = engine.disconnect() {\n    log::warn!(\"data client disconnect issues: {e}\");\n}","handlingStrategy":"try-catch","validationCode":"// Rust\n// check client connectivity before disconnecting\nlet dead: Vec<_> = client_ids.iter().filter(|id| !engine.is_client_connected(id)).collect();\nif !dead.is_empty() { log::warn!(\"clients already disconnected: {dead:?}\"); }","typeGuard":null,"tryCatchPattern":"// Rust\nmatch engine.disconnect() {\n    Ok(()) => {},\n    Err(e) => {\n        let inner = e.to_string();\n        for msg in inner.strip_prefix(\"Failed to disconnect data clients: \").unwrap_or(&inner).split(\"; \") {\n            log::warn!(\"disconnect issue: {msg}\");\n        }\n    }\n}","preventionTips":["Check client connection state before issuing disconnect.","Treat disconnect errors as non-fatal during shutdown and continue teardown.","Keep adapter logs alongside the aggregated error to find the failing client quickly."],"tags":["rust","data-engine","disconnect","aggregated-errors"],"backgroundTag":"http-request-failed","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"}