{"record":{"id":"40ad244c4624f98c","repo":"nautechsystems/nautilus_trader","slug":"failed-to-send-updatetradesubs-command-e","errorCode":null,"errorMessage":"Failed to send UpdateTradeSubs command: {e}","messagePattern":"Failed to send UpdateTradeSubs command: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/hyperliquid/src/websocket/client.rs","lineNumber":1550,"sourceCode":"        let coin = instrument.raw_symbol().inner();\n\n        let cmd_tx = self.cmd_tx.read().await;\n\n        // Update the handler's coin→instrument mapping for this subscription\n        cmd_tx\n            .send(HandlerCommand::UpdateInstrument(instrument.clone()))\n            .map_err(|e| anyhow::anyhow!(\"Failed to send UpdateInstrument command: {e}\"))?;\n\n        // Keep registry mutations and their handler commands ordered across\n        // concurrent generic/custom subscriptions for the same coin.\n        let _trade_stream_guard = self.trade_stream_lock.lock();\n        let registration = self.trade_streams.register(coin, stream_use);\n        cmd_tx\n            .send(HandlerCommand::UpdateTradeSubs {\n                coin,\n                uses: registration.uses,\n            })\n            .map_err(|e| anyhow::anyhow!(\"Failed to send UpdateTradeSubs command: {e}\"))?;\n\n        if registration.subscribe\n            && let Err(e) = self.send_subscription(&cmd_tx, SubscriptionRequest::Trades { coin })\n        {\n            let rollback = self.trade_streams.release(&coin, stream_use);\n            let _ = cmd_tx.send(HandlerCommand::UpdateTradeSubs {\n                coin,\n                uses: rollback.uses,\n            });\n            return Err(e);\n        }\n        Ok(())\n    }\n\n    /// Subscribe to mark price updates for an instrument.\n    pub async fn subscribe_mark_prices(&self, instrument_id: InstrumentId) -> anyhow::Result<()> {\n        self.subscribe_asset_context_data(instrument_id, AssetContextDataType::MarkPrice)\n            .await","sourceCodeStart":1532,"sourceCodeEnd":1568,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/hyperliquid/src/websocket/client.rs#L1532-L1568","documentation":"This error wraps a failed send of UpdateTradeSubs on the internal mpsc command channel during trades subscription. The command publishes the reference-counted stream uses for the coin so the handler keeps its registry in sync; the send fails only when the handler task's receiver is closed. It means the client's handler loop is no longer running.","triggerScenarios":"Calling subscribe_trades when the handler task exited between client creation and this send — after disconnect(), a handler panic, or dropping the task/receiver.","commonSituations":"Reusing a client after teardown; handler task aborted by its JoinHandle; process/runtime shutdown racing a subscribe; a panic inside the handler loop earlier in the session.","solutions":["Keep the handler task alive (spawn it and hold its JoinHandle) for as long as the client is used.","If the handler exited, re-create the client and resubscribe; the channel is unrecoverable.","Serialize disconnect and subscribe operations so shutdown cannot race a subscription attempt.","Enable panic hooks/logging on the handler task to find why the loop ended."],"exampleFix":"// before\nif shutdown_started {\n    tokio::spawn(client.run()); // spawned during shutdown, immediately cancelled\n}\nclient.subscribe_trades(instrument_id).await?;\n\n// after\nif !shutdown_started {\n    let handle = tokio::spawn(client.clone().run());\n    client.subscribe_trades(instrument_id).await?; // handler still alive\n    let _ = handle;\n}","handlingStrategy":"try-catch","validationCode":"// rust\nif !client.is_connected() {\n    return Err(anyhow::anyhow!(\"cannot subscribe trades: handler not running\"));\n}","typeGuard":null,"tryCatchPattern":"// rust\nif let Err(e) = client.subscribe_trades(instrument_id).await {\n    if e.to_string().contains(\"UpdateTradeSubs\") {\n        tracing::warn!(\"handler channel closed ({e}); reconnecting\");\n        client = reconnect_client().await?;\n        client.subscribe_trades(instrument_id).await?;\n    } else { return Err(e); }\n}","preventionTips":["Do not abort the handler JoinHandle while streams are active.","Guard subscribe calls with a shutdown flag checked before sending.","Log panics in the handler task to catch the root cause early.","On channel-send failure, always re-create the client; sends cannot be retried on a closed channel."],"tags":["rust","tokio","websocket","channel-closed","hyperliquid"],"backgroundTag":"broken-pipe","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"}