{"record":{"id":"fce14aeef2b8a6ae","repo":"nautechsystems/nautilus_trader","slug":"binance-spot-public-json-stream-pool-shutdown-bega-fce14a","errorCode":null,"errorMessage":"Binance Spot public JSON stream pool shutdown began during connect; rollback failed: {e}","messagePattern":"Binance Spot public JSON stream pool shutdown began during connect; rollback failed: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/binance/src/spot/websocket/public_json/client.rs","lineNumber":207,"sourceCode":"        let (out_tx, out_rx) = tokio::sync::mpsc::unbounded_channel();\n        *self.out_tx.lock() = Some(out_tx);\n        *self.out_rx.lock() = Some(out_rx);\n\n        let slot = self.create_connection(0).await?;\n        let shutdown = {\n            let mut slots = self.slots.lock();\n            let shutdown = self.signal.load(Ordering::Acquire);\n            slots.push(slot);\n            shutdown\n        };\n\n        if shutdown {\n            let rollback = self.close_connections().await;\n            return Err(match rollback {\n                Ok(()) => anyhow::anyhow!(\n                    \"Binance Spot public JSON stream pool shutdown began during connect\"\n                ),\n                Err(e) => anyhow::anyhow!(\n                    \"Binance Spot public JSON stream pool shutdown began during connect; rollback failed: {e}\"\n                ),\n            });\n        }\n\n        log::debug!(\n            \"Connected to Binance Spot public JSON stream pool: url={}\",\n            self.url\n        );\n        Ok(())\n    }\n\n    /// Closes all WebSocket connections and tasks.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if command delivery fails while shutting down.\n    pub async fn close(&mut self) -> anyhow::Result<()> {","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/binance/src/spot/websocket/public_json/client.rs#L189-L225","documentation":"This error means the public JSON stream pool began shutting down while a new connect() call was in flight. The client detects the shutdown flag mid-connect and attempts to roll back by closing any connections it already opened; if rollback itself fails, the rollback error is embedded in this message. It is a race-condition guard so a connecting client never leaks connections during shutdown.","triggerScenarios":"Calling connect() on BinanceSpotPublicJsonWsClient while another task is concurrently calling close_connections()/shutdown on the same pool, so the shutdown flag flips between the initial check and the end of connect.","commonSituations":"Application teardown (actor stop, SIGTERM handling, subscription cancellation) racing a startup sequence that is still establishing streams; tests or live loops that restart the data engine while initial connects are pending.","solutions":["Serialize pool lifecycle: ensure shutdown/close_connections() is not called until all connect() futures complete (await the connect handles before stopping).","Re-check pool state after connect and treat this error as expected during shutdown; do not retry connect if shutdown was intentional.","If the rollback failure matters, inspect the embedded {e} (usually a send-on-closed-channel to a dead handler) and ensure handlers are dropped after close_connections completes.","Use a shutdown-aware wrapper that suppresses this error once the pool's shutdown flag is observed."],"exampleFix":"// before\nlet pool = client.clone();\ntokio::spawn(async move { pool.connect().await });\npool.close_connections().await?;\n\n// after\nlet handle = tokio::spawn(client.clone().connect());\n// wait for in-flight connects before shutting down\nlet _ = handle.await;\nclient.close_connections().await?;","handlingStrategy":"try-catch","validationCode":"if pool.is_shutdown() {\n    return; // do not attempt connect during shutdown\n}","typeGuard":null,"tryCatchPattern":"match client.connect().await {\n    Err(e) if e.to_string().contains(\"shutdown began during connect\") => {\n        log::debug!(\"connect aborted by shutdown: {e}\"); // expected during teardown\n    }\n    Err(e) => return Err(e),\n    Ok(v) => Ok(v),\n}","preventionTips":["Await all in-flight connect() futures before calling close_connections()/shutdown.","Centralize pool lifecycle in one owner task to avoid concurrent connect/shutdown.","Use a shutdown flag check before initiating connects.","Treat this error as benign when teardown was intentional."],"tags":["race-condition","shutdown","websocket","lifecycle"],"backgroundTag":"invalid-state-transition","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"}