{"record":{"id":"38ebb548ddf7afd8","repo":"nautechsystems/nautilus_trader","slug":"errors-join","errorCode":null,"errorMessage":"{errors.join(\"; \")}","messagePattern":"\\{errors\\.join\\(\"; \"\\)\\}","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/binance/src/spot/websocket/public_json/client.rs","lineNumber":291,"sourceCode":"            {\n                batch.slots.remove(index);\n            }\n        }\n\n        *self.out_tx.lock() = None;\n        *self.out_rx.lock() = None;\n\n        let errors = batch\n            .slots\n            .iter_mut()\n            .flat_map(|slot| std::mem::take(&mut slot.shutdown_errors))\n            .collect::<Vec<_>>();\n        batch\n            .slots\n            .retain(|slot| slot.handler_task.is_some() || slot.bytes_task.is_some());\n\n        if !errors.is_empty() {\n            anyhow::bail!(errors.join(\"; \"));\n        }\n        log::debug!(\"Disconnected from Binance Spot public JSON stream pool\");\n        Ok(())\n    }\n\n    /// Subscribes to stream names.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if command delivery fails or if the connection pool is exhausted.\n    pub async fn subscribe(&self, streams: Vec<String>) -> anyhow::Result<()> {\n        let _connect_guard = self.connect_lock.lock().await;\n\n        // Phase 1: filter already-subscribed streams (brief lock)\n        let new_streams: Vec<String> = {\n            let slots = self.slots.lock();\n\n            if self.signal.load(Ordering::Acquire) {","sourceCodeStart":273,"sourceCodeEnd":309,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/binance/src/spot/websocket/public_json/client.rs#L273-L309","documentation":"close_connections tears down all slots in the public JSON stream pool and collects per-slot disconnect errors; if any slot failed to shut down cleanly it joins them with ';' and bails. The pool did disconnect its tasks, but at least one slot's handler/bytes task ended with an error during shutdown. This is an aggregated multi-error report.","triggerScenarios":"Calling close_connections (via connect to re-connect, or explicit close) when one or more slot handler_task or bytes_task join results contain errors — e.g. a task already crashed with a WS error, or shutdown signals failed to be acknowledged.","commonSituations":"Reconnecting after a network drop where some slot tasks already died with errors; closing the client while Binance is unreachable; tearing down during process shutdown where tasks fail cancellation.","solutions":["Inspect the joined error list to identify which slot(s) failed and whether the failure is transient (network) or persistent.","If transient, recreate/reconnect the client — connect() calls close_connections, so a fresh connect replaces the pool.","Ensure close is not called concurrently with subscribe/unsubscribe on the same pool.","If a slot task keeps failing, check stream names and connection stability; an already-dead task's error may be unavoidable at close time."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(e) = client.close().await {\n    log::warn!(\"disconnect reported errors (may be benign during shutdown): {e:#}\");\n}","preventionTips":["Treat aggregated shutdown errors as benign during application teardown.","Avoid calling close concurrently with active subscribe/unsubscribe traffic.","Monitor slot task health so failures surface before close, not only at close."],"tags":["websocket","binance","spot","shutdown","aggregated-errors"],"backgroundTag":"network-request-failed","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"}