nautechsystems/nautilus_trader · error

Strategy {strategy_id} is already registered

Error message

Strategy {strategy_id} is already registered

What it means

prepare_strategy_for_registration derives the final StrategyId (applying a per-strategy order id tag if given) and refuses to proceed if that id is already registered in trader.strategy_ids. This guard makes registration idempotent-safe: a strategy can only be registered once with the trader. It is the internal pre-check used by add_strategy.

Source

Thrown at crates/system/src/trader.rs:588

            ensure_unique_order_id_tag(&existing_order_id_tags, strategy_id.get_tag())?;
            StrategyNative::strategy_core_mut(strategy).change_id(strategy_id)?;
            strategy_id
        } else {
            let order_id_tag = runtime_order_id_tag.map_or_else(
                || format!("{:03}", existing_order_id_tags.len()),
                str::to_string,
            );
            ensure_unique_order_id_tag(&existing_order_id_tags, &order_id_tag)?;

            let base_id = strategy_registration_id::<T>(strategy);
            let strategy_id =
                StrategyId::new_checked(format!("{}-{order_id_tag}", base_strategy_id(&base_id)))?;
            StrategyNative::strategy_core_mut(strategy).change_id(strategy_id)?;
            strategy_id
        };

        if self.strategy_ids.contains(&strategy_id) {
            anyhow::bail!("Strategy {strategy_id} is already registered");
        }

        Ok(strategy_id)
    }

    /// Adds a strategy to the trader.
    ///
    /// Strategies are registered in both the component registry (for lifecycle management)
    /// and the actor registry (for data callbacks via msgbus). The strategy's `StrategyCore`
    /// is also registered with the portfolio for order management.
    ///
    /// # Errors
    ///
    /// Returns an error if:
    /// - The trader is not in a valid state for adding components.
    /// - A strategy with the same ID is already registered.
    pub fn add_strategy<T>(&mut self, mut strategy: T) -> anyhow::Result<()>
    where

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check that the strategy's StrategyId is not already in trader.strategy_ids before calling add_strategy.
  2. Give each strategy a unique name and unique order_id_tag so resolved ids cannot collide.
  3. If re-registering after a restart, create a fresh trader or remove/dispose the old strategy first.

Example fix

// before
trader.add_strategy(strategy)?;
trader.add_strategy(strategy)?; // panics/bails second time

// after
let strategy_id = StrategyNative::strategy_core(&strategy).id().clone();
if !trader.strategy_ids.contains(&strategy_id) {
    trader.add_strategy(strategy)?;
}
Defensive patterns

Strategy: validation

Validate before calling

let strategy_id = StrategyNative::strategy_core(&strategy).id().clone();
if trader.strategy_ids.contains(&strategy_id) {
    // skip or error early
}

Try / catch

match trader.add_strategy(strategy) {
    Err(e) if e.to_string().contains("already registered") => { /* idempotent skip */ }
    other => other?,
}

Prevention

When it happens

Trigger: Calling trader.add_strategy (directly or via prepare_strategy_for_registration) with a strategy whose resolved StrategyId already exists — e.g. adding the same strategy twice, or two strategies whose base name and order_id_tag resolve to the same id.

Common situations: Adding the same strategy object twice by accident in a loop over configs; duplicate order_id_tag values combined with identical strategy names producing colliding ids; re-running an init function without guarding against prior registration.

Related errors


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