nautechsystems/nautilus_trader · error
Already running
Error message
Already running
What it means
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.
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.
Example fix
// before
node.start().await?;
// later...
node.start().await?; // panics-free bail: Already running
// after
if !node.state().is_running() {
node.start().await?;
} Defensive patterns
Strategy: validation
Validate before calling
if node.state().is_running() { /* skip start */ } else { node.start().await?; } Type guard
fn can_start(node: &LiveNode) -> bool { !node.state().is_running() } Try / catch
if let Err(e) = node.start().await { if e.to_string() == "Already running" { /* treat as success / no-op */ } else { return Err(e); } } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Cannot add actor while node is running, add actors before…
- Cannot add strategy while node is running, add strategies…
- Cannot set cache database while node is running, set it…
- Failed to start Betfair data command tasks
- Failed to start Betfair data session tasks
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/a14b9ce1a10a4be0.
Report an issue: GitHub.
Appendix: source
Thrown at crates/live/src/node/mod.rs:392
F: Fn(&dyn Any, &serde_json::Value) -> anyhow::Result<()> + 'static,
{
self.stream_processors
.push(StreamProcessor(Box::new(callback)));
}
/// Starts the live node without entering a select loop.
///
/// Connects clients, runs reconciliation, and starts the trader, but does
/// not consume the runner or drive channel receivers, so channel traffic arriving after
/// startup is never serviced. This is a building block for tests and embedding, not a
/// lifecycle: use [`run`](Self::run) or [`run_with_mode`](Self::run_with_mode) to run a node.
///
/// # Errors
///
/// Returns an error if startup fails.
pub async fn start(&mut self) -> anyhow::Result<()> {
if self.state().is_running() {
anyhow::bail!("Already running");
}
if self.external_msgbus.is_some() {
log::warn!(
"External message bus ingress is configured but LiveNode::start() does not service it; use LiveNode::run()"
);
}
self.prepare_cache().await?;
if let Some(runner) = self.runner.as_ref() {
runner.bind_senders();
}
self.handle.set_starting();
self.kernel.reset_shutdown_flag();
self.kernel.start_async().await;View on GitHub (pinned to 18893faf8b)