{"record":{"id":"a14b9ce1a10a4be0","repo":"nautechsystems/nautilus_trader","slug":"already-running","errorCode":null,"errorMessage":"Already running","messagePattern":"Already running","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/live/src/node/mod.rs","lineNumber":392,"sourceCode":"        F: Fn(&dyn Any, &serde_json::Value) -> anyhow::Result<()> + 'static,\n    {\n        self.stream_processors\n            .push(StreamProcessor(Box::new(callback)));\n    }\n\n    /// Starts the live node without entering a select loop.\n    ///\n    /// Connects clients, runs reconciliation, and starts the trader, but does\n    /// not consume the runner or drive channel receivers, so channel traffic arriving after\n    /// startup is never serviced. This is a building block for tests and embedding, not a\n    /// lifecycle: use [`run`](Self::run) or [`run_with_mode`](Self::run_with_mode) to run a node.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if startup fails.\n    pub async fn start(&mut self) -> anyhow::Result<()> {\n        if self.state().is_running() {\n            anyhow::bail!(\"Already running\");\n        }\n\n        if self.external_msgbus.is_some() {\n            log::warn!(\n                \"External message bus ingress is configured but LiveNode::start() does not service it; use LiveNode::run()\"\n            );\n        }\n\n        self.prepare_cache().await?;\n\n        if let Some(runner) = self.runner.as_ref() {\n            runner.bind_senders();\n        }\n\n        self.handle.set_starting();\n\n        self.kernel.reset_shutdown_flag();\n        self.kernel.start_async().await;","sourceCodeStart":374,"sourceCodeEnd":410,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/live/src/node/mod.rs#L374-L410","documentation":"start() was called on a LiveActor/TradingNode whose kernel is already running; the node guards against double startup and returns this error instead of re-initializing clients, reconciliation, and the trader.","triggerScenarios":"Calling node.start() (or awaiting it) while the node state is already Running — e.g. start() called twice, or start() after run() has already started the node.","commonSituations":"Concurrent/reentrant start calls in async code without a guard; a retry wrapper that re-invokes start after a partial startup; calling start() manually after run() was already invoked.","solutions":["Check node.state().is_running() before calling start(), and skip if already running.","Call start() only once per node lifecycle; use the returned handle for control operations.","Stop the node first (if a restart is intended) before starting again.","Serialize start calls with a mutex/once-flag if multiple tasks may trigger them."],"exampleFix":"// before\nnode.start().await?;\n// later...\nnode.start().await?; // panics-free bail: Already running\n// after\nif !node.state().is_running() {\n    node.start().await?;\n}","handlingStrategy":"validation","validationCode":"if node.state().is_running() { /* skip start */ } else { node.start().await?; }","typeGuard":"fn can_start(node: &LiveNode) -> bool { !node.state().is_running() }","tryCatchPattern":"if let Err(e) = node.start().await { if e.to_string() == \"Already running\" { /* treat as success / no-op */ } else { return Err(e); } }","preventionTips":["Route all node control through one owner task or handle.","Guard start() with a OnceCell/flag in concurrent code.","Distinguish initial startup from restart; always stop before restarting."],"tags":["rust","state","lifecycle","async"],"backgroundTag":"invalid-state-transition","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}