{"record":{"id":"470730fec9d9c557","repo":"nautechsystems/nautilus_trader","slug":"live-runner-system-command-channel-is-closed","errorCode":null,"errorMessage":"Live runner system command channel is closed","messagePattern":"Live runner system command channel is closed","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/common/src/actor/data_actor.rs","lineNumber":5767,"sourceCode":"    pub fn reconnect_socket(&self, client_id: ClientId, endpoint: &str) -> anyhow::Result<()> {\n        let endpoint = socket_endpoint(endpoint)?;\n\n        if !self.is_properly_registered() {\n            anyhow::bail!(\n                \"Actor {} has not been registered with a Trader\",\n                self.actor_id\n            );\n        }\n\n        let sender = try_get_system_command_sender()\n            .ok_or_else(|| anyhow::anyhow!(\"Live runner system command channel is unavailable\"))?;\n        let trader_id = self\n            .trader_id\n            .ok_or_else(|| anyhow::anyhow!(\"Actor {} has no trader ID\", self.actor_id))?;\n        let command = ReconnectSocket::new(trader_id, client_id, endpoint, self.timestamp_ns());\n        sender\n            .send(SystemCommand::ReconnectSocket(command))\n            .map_err(|_| anyhow::anyhow!(\"Live runner system command channel is closed\"))?;\n        Ok(())\n    }\n\n    #[cfg(test)]\n    pub fn quote_handler_count(&self) -> usize {\n        self.quote_handlers.len()\n    }\n\n    #[cfg(test)]\n    pub fn trade_handler_count(&self) -> usize {\n        self.trade_handlers.len()\n    }\n\n    #[cfg(test)]\n    pub fn bar_handler_count(&self) -> usize {\n        self.bar_handlers.len()\n    }\n","sourceCodeStart":5749,"sourceCodeEnd":5785,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/common/src/actor/data_actor.rs#L5749-L5785","documentation":"After building the ReconnectSocket command, DataActor::reconnect_socket sends it over the system command channel. If the receiver end has been dropped the send fails, and the method maps that to 'Live runner system command channel is closed', meaning the live runner's system command consumer no longer exists.","triggerScenarios":"Calling reconnect_socket when the system command sender exists but its receiving side (the live runner's command loop) has been shut down or dropped — e.g. after node stop/disconnect or if the runner's command-handling task terminated.","commonSituations":"Requesting a socket reconnect during or after live-node shutdown; the live runner's system command task crashed or exited while actors keep running; holding an actor handle and calling reconnect after the TradingNode was stopped.","solutions":["Check node lifecycle state before calling reconnect_socket; only invoke it while the live runner is running.","Restart the trading node if its system command loop has shut down — the channel cannot be reattached at runtime.","Inspect runner logs for why the system command consumer exited (panic, task cancellation) and fix the root cause.","Handle the error gracefully in actor code (log and schedule reconnect after the node is back up) instead of retrying immediately."],"exampleFix":"// before\nactor.reconnect_socket(client_id, endpoint)?; // fails after node stopped\n\n// after\nif node.is_running() {\n    actor.reconnect_socket(client_id, endpoint)?;\n} else {\n    tracing::warn!(\"node not running; cannot send ReconnectSocket\");\n}","handlingStrategy":"retry","validationCode":"// Rust\nif !node.is_running() {\n    tracing::warn!(\"node not running; defer reconnect_socket\");\n    return Ok(());\n}","typeGuard":null,"tryCatchPattern":"match actor.reconnect_socket(client_id, endpoint) {\n    Ok(()) => {},\n    Err(e) if e.to_string().contains(\"channel is closed\") => {\n        tracing::warn!(\"system command channel closed; will retry after restart\");\n        schedule_reconnect_after_restart(client_id, endpoint);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Tie reconnect requests to the node's running state; never send after stop().","Monitor the live runner's system command task health so a crashed consumer is detected early.","On shutdown, cancel actor tasks that may still issue system commands."],"tags":["live-runner","channel-closed","system-command","shutdown"],"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"}