nautechsystems/nautilus_trader · error

Cannot add strategy while node is running, add strategies be

Error message

Cannot add strategy while node is running, add strategies before running the node

What it means

add_strategy (crates/live/src/node/mod.rs:2567) registers a strategy with the trader, capturing its external order claims and OMS type before it is moved. The node must be NodeState::Idle: strategies subscribe on the msgbus and may claim orders in the execution engine, which cannot be wired safely mid-run. Any state past Idle bails with this error.

Source

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

    /// Strategies 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.
    /// - A strategy with the same ID is already registered.
    /// - The strategy configures one or more external order claims and the request repeats
    ///   an instrument, or either tier already contains a requested claim.
    /// - The strategy configures one or more external order claims or an OMS type override,
    ///   and the execution engine is already borrowed. A strategy configuring neither does
    ///   not take the borrow and cannot fail this way.
    pub fn add_strategy<T>(&mut self, mut strategy: T) -> anyhow::Result<()>
    where
        T: Strategy + StrategyNative + DataActorNative + Component + Debug + 'static,
    {
        if self.state() != NodeState::Idle {
            anyhow::bail!(
                "Cannot add strategy while node is running, add strategies before running the node"
            );
        }

        // Capture strategy-owned values before adding the strategy, which moves it
        let strategy_id = self
            .kernel
            .trader
            .borrow()
            .prepare_strategy_for_registration(&mut strategy)?;
        let oms_type = StrategyNative::strategy_core(&strategy).config.oms_type;
        let claims = strategy.external_order_claims().unwrap_or_default();

        // The engine borrow is only needed for claims or an OMS override; a
        // strategy requiring neither must not fail on an unavailable borrow.
        let mut exec_engine = if claims.is_empty() && oms_type.is_none() {
            None
        } else {

View on GitHub (pinned to 2114cf6f76)

Solutions

  1. Register every strategy before run(), ideally through the node builder.
  2. For strategy churn, pre-register all candidate strategies and gate their behavior with config/flags instead of registering live.
  3. Build a new node with the full strategy set when the set must change.
  4. Check node.state() == NodeState::Idle before add_strategy in generic hosting code.
Defensive patterns

Strategy: validation

Validate before calling

if node.state() != NodeState::Idle {
    anyhow::bail!("cannot register strategies now; add strategies before running the node");
}
node.add_strategy(strategy)?;

Try / catch

if let Err(e) = node.add_strategy(strategy) {
    let msg = e.to_string();
    if msg.contains("while node is running") {
        log::error!("strategy registration must complete before run()");
    }
    return Err(e);
}

Prevention

When it happens

Trigger: Calling node.add_strategy(strategy) after the node started running or during shutdown; also triggered when code re-adds strategies to a node instance that already ran once.

Common situations: Dynamically deploying strategies in response to live signals; hosted apps loading strategy modules after launch; reusing a node across sessions and adding strategies in between.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@2114cf6f76 (2026-08-21). Data as JSON: /api/errors/20b61ca63f2b3217. Report an issue: GitHub.