{"record":{"id":"237ca93358dd9ade","repo":"nautechsystems/nautilus_trader","slug":"failed-to-set-spot-public-json-ws-client-e","errorCode":null,"errorMessage":"Failed to set Spot public JSON WS client: {e}","messagePattern":"Failed to set Spot public JSON WS client: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/binance/src/spot/websocket/public_json/client.rs","lineNumber":598,"sourceCode":"                Some(shutdown_error) => format!(\n                    \"Failed to start Spot public JSON WS bytes task: {e}; startup rollback failed: \\\n                     {shutdown_error}\"\n                ),\n                None => format!(\"Failed to start Spot public JSON WS bytes task: {e}\"),\n            });\n        }\n\n        let mut handler = BinanceSpotPublicWsHandler::new(\n            self.signal.clone(),\n            cmd_rx,\n            bytes_rx,\n            subscriptions_state.clone(),\n            self.request_id_counter.clone(),\n        );\n\n        cmd_tx\n            .send(BinanceSpotPublicWsCommand::SetClient(client))\n            .map_err(|e| anyhow::anyhow!(\"Failed to set Spot public JSON WS client: {e}\"))?;\n\n        let signal = self.signal.clone();\n        let token = cancellation_token.clone();\n        let resubscribe_tx = cmd_tx.clone();\n\n        let mut handler_task = TaskSlot::new();\n        if let Err(e) = handler_task.spawn(async move {\n            loop {\n                tokio::select! {\n                    () = token.cancelled() => {\n                        log::debug!(\"Spot public JSON handler task cancelled\");\n                        break;\n                    }\n                    result = handler.next() => {\n                        match result {\n                            Some(BinanceSpotPublicWsMessage::Reconnected) => {\n                                log::info!(\"Spot public JSON WebSocket reconnected, restoring subscriptions\");\n                                let topics = subscriptions_state.all_topics();","sourceCodeStart":580,"sourceCodeEnd":616,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/binance/src/spot/websocket/public_json/client.rs#L580-L616","documentation":"After connecting, create_connection() sends BinanceSpotPublicWsCommand::SetClient(client) to the freshly spawned handler task so it holds the live WS client. This error means that send failed because the handler task/channel is already gone — the handler exited immediately after being spawned.","triggerScenarios":"The handler task dies between spawn and the SetClient send — e.g. the cancellation token was already cancelled, the runtime is shutting down, or the handler task panicked on startup.","commonSituations":"Application/runtime shutdown racing connection setup; a bug or panic in the handler's initialization; spawning the task on a shutting-down tokio runtime; pool partially closed while subscribe()/connect() still runs.","solutions":["Retry the connect — a fresh create_connection will spawn a new handler; transient races usually resolve.","Check logs for handler task panics during startup and fix the panic root cause.","Ensure the runtime/cancellation token is not cancelled while connections are being established; complete connects before shutdown.","Verify the tokio runtime stays alive for the pool's lifetime (don't drop the runtime that spawned handler tasks)."],"exampleFix":"// before\nlet handle = tokio::spawn(handler_loop()); // runtime may be shutting down\nhandle.await?;\n\n// after\nif runtime_handle.runtime().is_none() || shutdown_flag.load(Ordering::SeqCst) {\n    return Err(anyhow!(\"cannot create connection during shutdown\"));\n}\nlet handle = runtime_handle.spawn(handler_loop());\nhandle.await?;","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"match client.connect().await {\n    Err(e) if e.to_string().contains(\"Failed to set Spot public JSON WS client\") => {\n        tokio::time::sleep(Duration::from_millis(500)).await;\n        client.connect().await?; // respawn handler and retry SetClient\n    }\n    r => r,\n}","preventionTips":["Keep the tokio runtime alive for the pool's entire lifetime.","Do not cancel the pool's cancellation token while connects are in flight.","Check handler task startup code for panics.","Sequence shutdown after all connection setup futures complete."],"tags":["websocket","channel-closed","task-panic","race-condition"],"backgroundTag":"internal-invariant-violation","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"}