nautechsystems/nautilus_trader · error

Cannot add exec algorithm while node is running, add exec…

Error message

Cannot add exec algorithm while node is running, add exec algorithms before running the node

What it means

`add_exec_algorithm` only permits registering execution algorithms while the node is in `NodeState::Idle`. Calling it after the node has started (state != Idle) is rejected because the execution engine is already running and cannot safely incorporate new algorithms. Register all exec algorithms during setup, before calling run.

Solutions

  1. Move all `add_exec_algorithm` calls before the node run call.
  2. Check `node.state() == NodeState::Idle` before calling add_exec_algorithm.
  3. If dynamic behavior is needed, configure the algorithm with internal logic that adapts at runtime instead of registering new ones.
  4. Restart the node with the full set of exec algorithms configured up front.

Example fix

// before
node.run()?;
node.add_exec_algorithm(MyAlgo::default())?;
// after
node.add_exec_algorithm(MyAlgo::default())?;
node.run()?;
Defensive patterns

Strategy: type-guard

Validate before calling

if node.state() != NodeState::Idle {
    panic!("register exec algorithms before running the node");
}
node.add_exec_algorithm(algo)?;

Type guard

fn can_register_exec_algo(node: &LiveNode) -> bool { node.state() == NodeState::Idle }

Try / catch

match node.add_exec_algorithm(algo) {
    Err(e) if e.to_string().contains("while node is running") => {
        eprintln!("defer registration: collect algos and register pre-run");
    }
    r => r?,
}

Prevention

When it happens

Trigger: Calling `node.add_exec_algorithm(algo)` after `node.run()` / `node.run_async()` has transitioned the node out of Idle; e.g. adding algorithms dynamically from a callback or after start.

Common situations: Trying to hot-swap or add a strategy's exec algorithm at runtime, or calling add_exec_algorithm after a first run in a long-lived process.

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/cd41a533460d2415. Report an issue: GitHub.

Appendix: source

Thrown at crates/live/src/node/mod.rs:2843

        cache.set_external_order_claims(strategy_id, &retained)
    }

    /// Adds an execution algorithm to the trader.
    ///
    /// Execution algorithms are registered in both the component registry (for lifecycle
    /// management) and the actor registry (for data callbacks via msgbus).
    ///
    /// # Errors
    ///
    /// Returns an error if:
    /// - The node is currently running.
    /// - An execution algorithm with the same ID is already registered.
    pub fn add_exec_algorithm<T>(&mut self, exec_algorithm: T) -> anyhow::Result<()>
    where
        T: ExecutionAlgorithm + ExecutionAlgorithmNative + Component + Debug + 'static,
    {
        if self.state() != NodeState::Idle {
            anyhow::bail!(
                "Cannot add exec algorithm while node is running, add exec algorithms before running the node"
            );
        }

        self.kernel
            .trader
            .borrow_mut()
            .add_exec_algorithm(exec_algorithm)
    }

    // Runs reconciliation sub-checks, each gated by its own interval.
    // Continuous checks only schedule venue work; they do not await venue I/O
    // in the event loop.
    fn run_reconciliation_checks(
        &mut self,
        now: dst::time::Instant,
        intervals: ReconciliationCheckIntervals,
        state: &mut ReconciliationCheckState<'_>,

View on GitHub (pinned to 18893faf8b)