{"record":{"id":"d4bd7d5355c4b8d4","repo":"nautechsystems/nautilus_trader","slug":"failed-to-send-unsubscribe-command-e-d4bd7d","errorCode":null,"errorMessage":"Failed to send unsubscribe command: {e}","messagePattern":"Failed to send unsubscribe command: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/hyperliquid/src/websocket/client.rs","lineNumber":2124,"sourceCode":"        }) {\n            if reserved {\n                self.rate_limits.release_subscription(self.client_id, &key);\n            }\n            anyhow::bail!(\"Failed to send subscribe command: {e}\");\n        }\n        Ok(())\n    }\n\n    fn send_unsubscription(\n        &self,\n        cmd_tx: &tokio::sync::mpsc::UnboundedSender<HandlerCommand>,\n        subscription: SubscriptionRequest,\n    ) -> anyhow::Result<()> {\n        cmd_tx\n            .send(HandlerCommand::Unsubscribe {\n                subscriptions: vec![subscription],\n            })\n            .map_err(|e| anyhow::anyhow!(\"Failed to send unsubscribe command: {e}\"))\n    }\n\n    /// Receives the next message from the WebSocket handler.\n    ///\n    /// Returns `None` if the handler has disconnected or the receiver was already taken.\n    pub async fn next_event(&mut self) -> Option<NautilusWsMessage> {\n        if let Some(ref mut rx) = self.out_rx {\n            rx.recv().await\n        } else {\n            None\n        }\n    }\n\n    fn release_limit_reservations(&self) {\n        self.rate_limits.release_client(self.client_id);\n        self.connection_permit.lock().take();\n    }\n}","sourceCodeStart":2106,"sourceCodeEnd":2142,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/hyperliquid/src/websocket/client.rs#L2106-L2142","documentation":"This error is returned by send_unsubscription when the Unsubscribe HandlerCommand cannot be sent to the handler task over the command channel. The channel being closed means the handler task that processes unsubscriptions has terminated.","triggerScenarios":"Any call to unsubscribe(...) after the handler task has dropped its receiver — e.g. after a disconnect, handler panic, or client close while an unsubscribe is still pending.","commonSituations":"Application shutdown where cleanup calls unsubscribe after the connection already closed; a crashed handler task; using a client handle from a previous connection session.","solutions":["Guard unsubscribe calls with a connection-alive check","If disconnected, drop local state instead of sending the command","Reconnect/recreate the client before further use","Check logs for a prior handler task panic"],"exampleFix":"// before\nclient.unsubscribe(data_type).await?;\n// after\nif client.is_connected() {\n    client.unsubscribe(data_type).await?;\n} else {\n    log::warn!(\"skipping unsubscribe, handler disconnected\");\n}","handlingStrategy":"try-catch","validationCode":"// Rust\nfn should_unsubscribe(client: &HyperliquidWsClient) -> bool {\n    client.is_connected()\n}","typeGuard":null,"tryCatchPattern":"if client.is_connected() {\n    client.unsubscribe(sub).await?;\n} else {\n    log::debug!(\"handler disconnected; skipping unsubscribe\");\n}","preventionTips":["Guard cleanup paths with connection checks","Handle shutdown ordering: unsubscribe before close()","Ignore send-to-closed-channel errors during teardown","Recreate clients after teardown instead of reuse"],"tags":["websocket","channel-closed","unsubscribe","rust"],"backgroundTag":"broken-pipe","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"}