nautechsystems/nautilus_trader · error

Strategy '{strategy_id}' is already tracked by trader

Error message

Strategy '{strategy_id}' is already tracked by trader

What it means

Trader.add_strategy_id_with_subscriptions rejects a StrategyId that is already present in the trader's tracked strategy_ids set. The trader maintains one registration per strategy so subscriptions and order routing stay unambiguous. Registering the same strategy twice would double subscriptions and corrupt id-based lookups, so it is refused up front. A related uniqueness check follows for order id tags.

Source

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

    /// Adds an externally-registered strategy to the trader for lifecycle management
    /// and installs its order/position event subscriptions, stop hook, and control endpoint.
    ///
    /// The strategy must already be registered in the global component and actor
    /// registries. The generic parameter `T` must match the concrete type stored
    /// in those registries so that the typed event handlers can retrieve it.
    ///
    /// # Errors
    ///
    /// Returns an error if the strategy ID is already tracked by this trader.
    pub fn add_strategy_id_with_subscriptions<T>(
        &mut self,
        strategy_id: StrategyId,
    ) -> anyhow::Result<()>
    where
        T: Strategy + StrategyNative + DataActorNative + Component + Debug + 'static,
    {
        if self.strategy_ids.contains(&strategy_id) {
            anyhow::bail!("Strategy '{strategy_id}' is already tracked by trader");
        }

        let existing_order_id_tags: Vec<&str> =
            self.strategy_ids.iter().map(StrategyId::get_tag).collect();
        ensure_unique_order_id_tag(&existing_order_id_tags, strategy_id.get_tag())?;

        let actor_id = strategy_id.inner();

        // Subscribe to order events for this strategy
        let order_topic = get_event_order_topic(strategy_id);
        let order_actor_id = actor_id;
        let order_handler = TypedHandler::from(move |event: &OrderEventAny| {
            if let Some(mut strategy) = try_get_actor_unchecked::<T>(&order_actor_id) {
                strategy.handle_order_event(event.clone());
            } else {
                log::error!("Strategy {order_actor_id} not found for order event handling");
            }
        });

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check trader.strategy_ids (or keep your own registry) before calling add_strategy_id_with_subscriptions and skip if the id is present.
  2. Assign each strategy a distinct StrategyId (unique name + order id tag) when constructing it.
  3. If this follows a failed add, reset or rebuild the trader instead of re-adding onto a partially initialized state.

Example fix

// before
trader.add_strategy_id_with_subscriptions(strategy_id, strategy)?;

// after
if !trader.strategy_ids.contains(&strategy_id) {
    trader.add_strategy_id_with_subscriptions(strategy_id, strategy)?;
} else {
    // strategy already tracked; skip registration
}
Defensive patterns

Strategy: validation

Validate before calling

if trader.strategy_ids.contains(&strategy_id) {
    // skip registration or use a fresh StrategyId
}

Try / catch

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

Prevention

When it happens

Trigger: Calling add_strategy_id_with_subscriptions with a StrategyId whose inner value already exists in trader.strategy_ids — e.g. adding the same strategy instance twice, or re-running an add path after a partially failed setup that already recorded the id.

Common situations: Application bootstrap code that calls trader.add_strategy on restart without checking whether the strategy was already added; idempotency wrappers that retry after an ambiguous failure; tests re-adding a strategy with the same StrategyId.

Related errors


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