nautechsystems/nautilus_trader · error · anyhow::Error

Strategy not registered: strategy_id is not set

Error message

Strategy not registered: strategy_id is not set

What it means

Raised by `registered_strategy_id` when `StrategyCore.strategy_id()` is None, i.e. the strategy has no StrategyId because it was never registered. Callers use it to stamp commands and cache entries with the strategy identity before order operations.

Source

Thrown at crates/trading/src/strategy/mod.rs:2443

    msgbus::send_trading_command(endpoint, command);
}

fn log_cmd_send(command: &TradingCommand) {
    if let Some(id) = command.strategy_id() {
        log::info!("{id} {CMD}{SEND} {command}");
    } else {
        log::info!("{CMD}{SEND} {command}");
    }
}

fn registered_trader_id(core: &StrategyCore) -> anyhow::Result<TraderId> {
    core.trader_id()
        .ok_or_else(|| anyhow::anyhow!("Strategy not registered: trader_id is not set"))
}

fn registered_strategy_id(core: &StrategyCore) -> anyhow::Result<StrategyId> {
    core.strategy_id()
        .ok_or_else(|| anyhow::anyhow!("Strategy not registered: strategy_id is not set"))
}

fn required_account_id(order: &OrderAny, operation: &str) -> anyhow::Result<AccountId> {
    order.account_id().ok_or_else(|| {
        anyhow::anyhow!(
            "Cannot generate {operation} event for {}: account_id is not set",
            order.client_order_id()
        )
    })
}

#[cfg(test)]
mod tests {
    use std::{cell::RefCell, rc::Rc};

    use nautilus_common::{
        actor::{
            DataActor,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Add the strategy to the trading node (trader.add_strategy) before issuing order operations.
  2. Confirm the strategy's on_start/registration path ran (strategy_id set during register).
  3. Use the framework's builder or fixtures to construct and register strategies in tests.
  4. Guard entry points with a registered check if the strategy can be used pre-registration.

Example fix

// before
let strategy = MyStrategy::new(config);
strategy.cancel_all_orders(None)?; // strategy_id unset
// after
let strategy = trader.add_strategy(MyStrategy::new(config))?;
strategy.cancel_all_orders(None)?;
Defensive patterns

Strategy: validation

Validate before calling

if strategy.core().strategy_id().is_none() { return Err("strategy_id unset: register strategy first".into()); }

Try / catch

if let Err(e) = strategy.cancel_all_orders(None) {
    if e.to_string().contains("strategy_id is not set") { log::error!("strategy never registered: {e}"); }
}

Prevention

When it happens

Trigger: Calling set_external_order_instrument_ids, submit_order_list, modify_order(s), cancel_order(s) on an unregistered strategy instance (constructed but never added to a trader/node).

Common situations: Same as trader_id case: manually constructed strategies in scripts/tests, strategies removed from the trader, or a failed/incomplete registration flow.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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