{"record":{"id":"0a071de2fe218904","repo":"nautechsystems/nautilus_trader","slug":"failed-to-start-polymarket-websocket-handler-task","errorCode":null,"errorMessage":"Failed to start Polymarket WebSocket handler task: {e}","messagePattern":"Failed to start Polymarket WebSocket handler task: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/websocket/client.rs","lineNumber":386,"sourceCode":"                                log::error!(\"Output channel closed, stopping handler\");\n                            }\n                            break;\n                        }\n                    }\n                    None => {\n                        if handler.is_stopped() {\n                            log::debug!(\"Stop signal received, ending handler task\");\n                        } else {\n                            log::warn!(\"Polymarket WebSocket stream ended unexpectedly\");\n                        }\n                        break;\n                    }\n                }\n            }\n            log::debug!(\"Polymarket WebSocket handler task completed\");\n        }) {\n            self.out_rx = None;\n            anyhow::bail!(\"Failed to start Polymarket WebSocket handler task: {e}\");\n        }\n        Ok(())\n    }\n\n    fn websocket_config(&self) -> WebSocketConfig {\n        // The market endpoint rejects text PING before its initial subscription. Protocol pings\n        // keep an idle socket alive until FeedHandler starts the required text heartbeat.\n        let heartbeat_payload = match self.channel {\n            WsChannel::Market => None,\n            WsChannel::User => Some(POLYMARKET_HEARTBEAT_PAYLOAD.to_string()),\n        };\n\n        WebSocketConfig {\n            url: self.url.clone(),\n            headers: vec![],\n            heartbeat_interval_secs: Some(POLYMARKET_HEARTBEAT_SECS),\n            heartbeat_payload,\n            connect_timeout_ms: Some(15_000),","sourceCodeStart":368,"sourceCodeEnd":404,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/websocket/client.rs#L368-L404","documentation":"connect() spawns a tokio task that drives the Polymarket WebSocket read loop and forwards messages through out_rx. If spawning fails (e.g. the runtime is shutting down or no runtime is active), the method restores out_rx to None and aborts the connection attempt with this error.","triggerScenarios":"Calling connect() on a PolymarketWebSocketClient while the tokio runtime is being torn down, inside a runtime drop, or via tokio::spawn with no reactor (e.g. running async code outside #[tokio::main]/block_on).","commonSituations":"Graceful shutdown racing with a reconnect attempt; spawning the client in a plain std::thread without a runtime; nested runtime misuse with tokio::spawn.","solutions":["Ensure connect() (and all client async calls) run inside an active, live tokio runtime","Guard reconnection logic so it is cancelled during shutdown (select! on a shutdown signal before spawning)","Check the wrapped error `e` — spawn failures usually mean JoinHandle/panics in the task body; fix the panic","Retry the connect after runtime is confirmed healthy; verify out_rx was reset to None so state stays consistent"],"exampleFix":"// before\nlet handle = tokio::spawn(async { /* read loop */ });\n// after\nmatch tokio::runtime::Handle::try_current() {\n    Ok(h) => { let handle = h.spawn(async { /* read loop */ }); ... }\n    Err(e) => anyhow::bail!(\"no active tokio runtime: {e}\"),\n}","handlingStrategy":"retry","validationCode":"// ensure an active runtime before connect\nif tokio::runtime::Handle::try_current().is_err() {\n    anyhow::bail!(\"PolymarketWebSocketClient::connect requires a live tokio runtime\");\n}","typeGuard":null,"tryCatchPattern":"match client.connect().await {\n    Ok(()) => {},\n    Err(e) if e.to_string().contains(\"Failed to start Polymarket WebSocket handler task\") => {\n        tokio::time::sleep(Duration::from_millis(200)).await;\n        client.connect().await?; // retry once runtime confirmed healthy\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Never spawn the client outside a tokio runtime","Cancel reconnect loops during shutdown before tasks are dropped","Check that the handler task body cannot panic"],"tags":["rust","tokio","websocket","polymarket"],"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-14T05:17:10.506Z"}