{"record":{"id":"69696f16a9da084e","repo":"nautechsystems/nautilus_trader","slug":"failed-to-send-setclient-command-e-69696f","errorCode":null,"errorMessage":"Failed to send SetClient command: {e}","messagePattern":"Failed to send SetClient command: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/hyperliquid/src/websocket/client.rs","lineNumber":359,"sourceCode":"            control.register(move || handle.request_reconnect());\n        }\n\n        // Create channels for handler communication\n        let (cmd_tx, cmd_rx) = tokio::sync::mpsc::unbounded_channel::<HandlerCommand>();\n        let (out_tx, out_rx) = tokio::sync::mpsc::unbounded_channel::<NautilusWsMessage>();\n\n        // Update cmd_tx before connection_mode to avoid race where is_active() returns\n        // true but subscriptions still go to the old placeholder channel\n        *self.cmd_tx.write().await = cmd_tx.clone();\n        self.out_rx = Some(out_rx);\n\n        self.connection_mode.store(client.connection_mode_atomic());\n        log::debug!(\"Hyperliquid WebSocket connected: {}\", self.url);\n\n        // Send SetClient command immediately\n        if let Err(e) = cmd_tx.send(HandlerCommand::SetClient(client)) {\n            self.release_limit_reservations();\n            anyhow::bail!(\"Failed to send SetClient command: {e}\");\n        }\n\n        // Initialize handler with existing instruments\n        let instruments_vec: Vec<InstrumentAny> =\n            self.instruments.load().values().cloned().collect();\n\n        if !instruments_vec.is_empty()\n            && let Err(e) = cmd_tx.send(HandlerCommand::InitializeInstruments(instruments_vec))\n        {\n            log::error!(\"Failed to send InitializeInstruments: {e}\");\n        }\n\n        for (coin, uses) in self.trade_streams.snapshot() {\n            if let Err(e) = cmd_tx.send(HandlerCommand::UpdateTradeSubs { coin, uses }) {\n                log::error!(\"Failed to send UpdateTradeSubs: {e}\");\n            }\n        }\n","sourceCodeStart":341,"sourceCodeEnd":377,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/hyperliquid/src/websocket/client.rs#L341-L377","documentation":"Raised in HyperliquidWebSocketClient::connect_locked when the mpsc send of HandlerCommand::SetClient to the background WebSocket handler task fails. A failed send means the handler task's command-channel receiver has already been dropped, i.e. the handler exited or was never spawned, so the client cannot be registered with it and the connection cannot proceed. The client releases reserved rate-limiter slots before bailing so retries start from a clean state.","triggerScenarios":"Calling connect() when the receiving half of cmd_tx has been dropped: after a previous disconnect, after the handler task panicked or completed early, or when the receiver end was closed before this send.","commonSituations":"Reconnecting a client after a prior disconnect without recreating the channel; a handler task crash caused by a malformed message; racing concurrent connect()/disconnect() calls so the task shuts down mid-connect; reusing a stale client instance across reconnect attempts.","solutions":["Recreate the WebSocket client (a fresh instance re-establishes the command channel and handler task) and retry connect().","Check logs immediately before this error for handler-task panics or early exits and fix the underlying cause.","Serialize connect()/disconnect() calls to avoid racing shutdown against connection setup.","Verify no code path drops the command receiver prematurely during setup."],"exampleFix":"// before: reuse stale client after disconnect -> channel closed / client.connect().await?; / // after: rebuild client so cmd channel + handler task are recreated / let mut client = HyperliquidWebSocketClient::new(url, ...); / client.connect().await?;","handlingStrategy":"try-catch","validationCode":"fn handler_alive(cmd_tx: &tokio::sync::mpsc::Sender<HandlerCommand>) -> bool { !cmd_tx.is_closed() }","typeGuard":"fn handler_alive(cmd_tx: &tokio::sync::mpsc::Sender<HandlerCommand>) -> bool { !cmd_tx.is_closed() }","tryCatchPattern":"match client.connect().await { Err(e) if e.to_string().contains(\"Failed to send SetClient command\") => { client = HyperliquidWebSocketClient::new(url, ...); client.connect().await?; } Err(e) => return Err(e), Ok(()) => {} }","preventionTips":["Treat client instances as single-use per connection lifecycle; rebuild on reconnect.","Never call connect() on a client previously passed to disconnect().","Serialize connection lifecycle calls to prevent disconnect racing connect.","Monitor logs for handler-task exits so you reconnect before subscriptions fail."],"tags":["websocket","async","channel-closed","connection"],"backgroundTag":"connection-refused","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"}