nautechsystems/nautilus_trader · critical

Execution client should be initialized

Error message

Execution client should be initialized

What it means

The backtest exchange panicked because a trading command required a portfolio execution client, but `self.exec_client` was `None`. In NautilusTrader's backtest engine the SimulatedExchange needs an initialized execution client to resolve the account that will process order submissions. This is an internal invariant of the backtest engine: `execute` was called before the client was wired up.

Source

Thrown at crates/backtest/src/exchange.rs:1872

                return;
            }
            TradingCommand::ModifyOrders(mut command) => {
                command
                    .modifies
                    .retain(|modify| !self.process_modify_submitted_order(modify));

                if command.modifies.is_empty() {
                    return;
                }
                TradingCommand::ModifyOrders(command)
            }
            command => command,
        };

        let account_id = if let Some(exec_client) = &self.exec_client {
            exec_client.account_id()
        } else {
            panic!("Execution client should be initialized");
        };

        if let TradingCommand::SubmitOrderList(ref command) = command {
            let mut orders: Vec<OrderAny> = self
                .cache
                .borrow()
                .orders_for_ids(&command.order_list.client_order_ids, command);

            for order in &mut orders {
                let order_instrument_id = order.instrument_id();
                if let Some(matching_engine) = self.matching_engines.get_mut(&order_instrument_id) {
                    matching_engine.process_order(order, account_id);
                } else {
                    panic!("Matching engine not found for instrument {order_instrument_id}");
                }
            }

            return;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Add the execution client to the backtest before executing commands (e.g. add a `SimulatedExchangeConfig`/venue with execution enabled or call the engine's exec-client registration API).
  2. Ensure `BacktestEngine.add_venue(...)` (or equivalent setup) runs before any `execute`/command submission.
  3. Check the order of initialization so `exec_client` is set before the data loop starts processing commands.

Example fix

// before
let mut engine = BacktestEngine::new();
engine.add_data(...);
engine.run(); // panic: no exec client
// after
let mut engine = BacktestEngine::new();
engine.add_venue(SimulatedExchangeConfig::default());
engine.add_data(...);
engine.run();
Defensive patterns

Strategy: validation

Validate before calling

// before running the backtest
assert!(engine.exec_client_account_id().is_some(), "Add a venue/exec client config before executing commands");

Prevention

When it happens

Trigger: Calling `SimulatedExchange.execute(...)` with a `SubmitOrderList` (or other `TradingCommand`) when no execution client was registered via `set_exec_client(...)` / the builder was not fully configured.

Common situations: Programmatically constructing a `BacktestEngine` or `SimulatedExchange` and forgetting to add the execution client/venue configuration; constructing an exchange by hand in tests without calling the exec-client setter; version changes in the backtest builder API where the setup call was renamed or dropped.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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