{"record":{"id":"246feeaa5a0003ac","repo":"nautechsystems/nautilus_trader","slug":"errors-join-246fee","errorCode":null,"errorMessage":"errors.join(\"; \")","messagePattern":"errors\\.join\\(\"; \"\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/bybit/src/data.rs","lineNumber":264,"sourceCode":"        let (session_result, command_result) = tokio::join!(\n            self.session_tasks\n                .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!(\"failed to finish Bybit data session tasks: {e}\"));\n        }\n\n        if let Err(e) = command_result {\n            errors.push(format!(\"failed to finish Bybit data command tasks: {e}\"));\n        }\n\n        if errors.is_empty() {\n            Ok(())\n        } else {\n            anyhow::bail!(errors.join(\"; \"))\n        }\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 Bybit data session task generation\")?;\n            self.command_tasks\n                .start_generation()\n                .context(\"failed to start Bybit data command task generation\")?;\n            self.cancellation_token = self.session_tasks.cancellation_token();\n        }\n        Ok(())\n    }\n\n    fn spawn_ws<F>(&self, fut: F, context: &'static str)","sourceCodeStart":246,"sourceCodeEnd":282,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/bybit/src/data.rs#L246-L282","documentation":"During teardown of the Bybit data client, finish_tasks joins session and command tasks; any task that fails to finish is collected as a message. If any errors accumulated, the whole operation bails with all messages joined by \"; \". This indicates background websocket/HTTP tasks did not shut down cleanly during connect/teardown.","triggerScenarios":"Calling connect (via prepare_task_groups -> teardown_partial_connect) or disconnect when one or more spawned data command tasks returned an error like \"failed to finish Bybit data command tasks: ...\".","commonSituations":"Network drops mid-connect leaving tasks in a bad state; exchange websocket closing unexpectedly during startup/shutdown; partial connect failures where some tasks already errored.","solutions":["Read the joined messages to identify which tasks failed and the root cause","Check network/proxy stability and Bybit exchange status","Retry the connection after the failed teardown","If persistent, capture logs and file an issue with the specific task error"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// before connect: check connectivity to Bybit endpoints\nasync fn bybit_reachable() -> bool { reqwest::get(\"https://api.bybit.com/v5/market/time\").await.is_ok() }","typeGuard":null,"tryCatchPattern":"match client.connect().await {\n    Ok(()) => {},\n    Err(e) => {\n        log::error!(\"Bybit data connect/teardown failed: {e:#}\");\n        tokio::time::sleep(BACKOFF).await;\n        retry_connect();\n    }\n}","preventionTips":["Ensure stable network/proxy before connecting","Monitor Bybit status during startup","Treat the joined message list as the diagnostic — read every task error","Add exponential backoff on connect retries"],"tags":["bybit","shutdown","task-join","websocket"],"backgroundTag":"connection-refused","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}