{"record":{"id":"e12932b343c3a046","repo":"nautechsystems/nautilus_trader","slug":"binance-spot-data-teardown-failed","errorCode":null,"errorMessage":"Binance Spot data teardown failed: {}","messagePattern":"Binance Spot data teardown failed: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/binance/src/spot/data.rs","lineNumber":341,"sourceCode":"    }\n\n    async fn teardown_partial_connect(&mut self) -> anyhow::Result<()> {\n        self.session_tasks.begin_shutdown();\n        self.command_tasks.begin_shutdown();\n        self.ws_client.begin_shutdown();\n        if let Err(e) = self.ws_client.close().await {\n            self.shutdown_errors\n                .push(format!(\"WebSocket close failed: {e}\"));\n        }\n\n        if let Err(e) = self.finish_tasks().await {\n            self.shutdown_errors.push(e.to_string());\n        }\n        self.is_connected.store(false, Ordering::Release);\n\n        if !self.shutdown_errors.is_empty() {\n            let errors = std::mem::take(&mut self.shutdown_errors);\n            anyhow::bail!(\"Binance Spot data teardown failed: {}\", errors.join(\"; \"));\n        }\n        Ok(())\n    }\n\n    #[expect(clippy::too_many_arguments)]\n    async fn refresh_instrument_catalog(\n        http: &BinanceSpotHttpClient,\n        provider: &crate::config::BinanceInstrumentProviderConfig,\n        us: bool,\n        instruments_cache: &Arc<AtomicMap<InstrumentId, InstrumentAny>>,\n        status_cache: &Arc<AtomicMap<InstrumentId, MarketStatusAction>>,\n        ws: &SpotWsClient,\n        sender: &tokio::sync::mpsc::UnboundedSender<DataEvent>,\n        clock: &'static AtomicTime,\n        emit_status_changes: bool,\n    ) -> anyhow::Result<Vec<InstrumentAny>> {\n        let instruments = http\n            .request_instruments_with_config(provider, us)","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/binance/src/spot/data.rs#L323-L359","documentation":"Raised in `teardown_partial_connect` of the Binance Spot data client when one or more teardown/shutdown tasks (e.g. websocket disconnections, stream shutdowns) fail while cleaning up a partially established or closing connection. The client accumulates each failure message in `shutdown_errors`, marks itself disconnected, and bails with all messages joined by '; '. It signals that a disconnect or partial connect cleanup did not fully succeed, though the client is still flagged offline.","triggerScenarios":"Calling `disconnect()` (or a `connect()` that fails partway and runs cleanup via `prepare_task_groups`) while websocket/stream shutdown tasks return errors; each failed shutdown pushes `e.to_string()` into `shutdown_errors`, and if non-empty the joined message is raised.","commonSituations":"Network outage or proxy drop during disconnect causing ws close to fail; Binance REST 4xx/5xx on session-termination calls; timeouts when closing streams on a slow connection; cancelling `connect()` mid-way so cleanup tasks run against half-initialized state.","solutions":["Read the joined messages after the prefix to identify which teardown step(s) failed; the client is already marked disconnected so reconnect via `connect()` is usually safe","Check network/proxy reachability to Binance endpoints (api.binance.com, ws streams) at the time of teardown","Increase any disconnect/shutdown timeout in the adapter config so slow closes are not aborted","Retry disconnect once; transient network errors during close are common and often succeed on retry","If errors persist on every disconnect, enable debug logging and report the specific failing shutdown task"],"exampleFix":"// before\ndata_client.disconnect().await.unwrap();\n// after\nif let Err(e) = data_client.disconnect().await {\n    log::warn!(\"Binance Spot data teardown issue (client still disconnected): {e:#}\");\n}","handlingStrategy":"try-catch","validationCode":"// before disconnecting, confirm network reachability\n// ping Binance REST endpoint with a short timeout\nlet ok = tokio::time::timeout(Duration::from_secs(5), reqwest::get(\"https://api.binance.com/api/v3/ping\")).await.is_ok();","typeGuard":null,"tryCatchPattern":"match client.disconnect().await {\n    Ok(()) => {},\n    Err(e) if e.to_string().contains(\"teardown failed\") => {\n        // client is already flagged disconnected; log and proceed with reconnect\n        log::warn!(\"teardown error (non-fatal): {e:#}\");\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Disconnect while network connectivity is confirmed healthy","Allow generous shutdown timeouts for websocket/stream closes","Inspect shutdown_errors messages to identify the failing teardown task and address it at the source"],"tags":["rust","network","websocket","teardown","binance"],"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-14T00:17:10.932Z"}