{"record":{"id":"821d3883bf1989ce","repo":"nautechsystems/nautilus_trader","slug":"failed-to-finish-binance-futures-data-command-task","errorCode":null,"errorMessage":"failed to finish Binance Futures data command tasks: {e}","messagePattern":"failed to finish Binance Futures data command tasks: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/adapters/binance/src/futures/data.rs","lineNumber":336,"sourceCode":"                .finish_shutdown(Duration::from_secs(1), Duration::from_secs(2)),\n            self.command_tasks\n                .finish_shutdown(Duration::from_secs(1), Duration::from_secs(2)),\n        );\n        let mut errors = Vec::new();\n        if let Err(e) = session_result {\n            errors.push(format!(\n                \"failed to finish Binance Futures data session tasks: {e}\"\n            ));\n        }\n\n        if let Err(e) = command_result {\n            errors.push(format!(\n                \"failed to finish Binance Futures data command tasks: {e}\"\n            ));\n        }\n\n        if !errors.is_empty() {\n            anyhow::bail!(errors.join(\"; \"));\n        }\n        Ok(())\n    }\n\n    async fn prepare_task_groups(&mut self) -> anyhow::Result<()> {\n        if !self.session_tasks.is_open() || !self.command_tasks.is_open() {\n            self.teardown_partial_connect().await?;\n            self.session_tasks\n                .start_generation()\n                .context(\"failed to start Binance Futures data session task generation\")?;\n            self.command_tasks\n                .start_generation()\n                .context(\"failed to start Binance Futures data command task generation\")?;\n            self.cancellation_token = self.session_tasks.cancellation_token();\n        }\n        Ok(())\n    }\n","sourceCodeStart":318,"sourceCodeEnd":354,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/binance/src/futures/data.rs#L318-L354","documentation":"During Binance Futures data client shutdown, `finish_tasks` waits for both the session and command task groups to finish (1s/2s timeouts). If the command task group's `finish_shutdown` returns an error, it is collected into a combined message and bailed. This signals command-related WebSocket/subscription tasks did not shut down cleanly.","triggerScenarios":"Calling teardown_partial_connect (from prepare_task_groups, connect, or disconnect) while command tasks (subscription/unsubscription futures) hang or fail to complete within the 1s drain/2s timeout, or the underlying task join fails (e.g. WebSocket already in a broken state).","commonSituations":"Network partitions during shutdown, disconnect/reconnect races, calling disconnect while subscription commands are still in flight, or repeated connect/disconnect cycles that left task groups in a bad state.","solutions":["Check logs for the paired 'failed to finish Binance Futures data session tasks' message to identify which task group hung","Ensure the network connection is healthy and the WebSocket close is not blocked by a hung socket before disconnecting","Avoid overlapping connect/disconnect calls; let the previous shutdown complete","Retry the disconnect; the teardown sets is_connected=false regardless, so state is consistent","Upgrade the adapter if timeouts are consistently too short for your latency profile"],"exampleFix":"// before\nclient.disconnect();\nclient.subscribe(cmd); // overlapping work during shutdown\n// after\nclient.disconnect().await?; // ensure teardown completes first\nclient.subscribe(cmd);","handlingStrategy":"try-catch","validationCode":"assert!(session_tasks.is_open() && command_tasks.is_open(), \"task groups must be open before disconnect\");","typeGuard":null,"tryCatchPattern":"match client.disconnect().await {\n    Err(e) if e.to_string().contains(\"teardown failed\") => log::warn!(\"task shutdown issue: {e}\"),\n    Err(e) => return Err(e),\n    Ok(()) => Ok(()),\n}","preventionTips":["Do not overlap connect/disconnect calls","Ensure network is healthy before disconnecting","Retry disconnect once on teardown errors"],"tags":["rust","tokio","websocket","shutdown"],"backgroundTag":"request-timeout","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"}