nautechsystems/nautilus_trader · error

Cannot generate {operation} event for {}: account_id is not

Error message

Cannot generate {operation} event for {}: account_id is not set

What it means

Execution algorithms require every order they act on to carry an AccountId, because generated modify/cancel order events must be attributed to the account that owns the order. `required_account_id` extracts the order's account_id and throws this anyhow error when it is None (the order was constructed without an account). This guards downstream event generation (e.g. OrderModify/OrderCancel events) from being emitted for an order the execution layer cannot attribute.

Source

Thrown at crates/trading/src/algorithm/mod.rs:1541

fn publish_order_initialized(order: &OrderAny) {
    let event = OrderEventAny::Initialized(order.init_event().clone());
    publish_order_event(&event);
}

fn publish_order_event(event: &OrderEventAny) {
    let topic = format!("events.order.{}", event.strategy_id());
    msgbus::publish_order_event(topic.into(), event);
}

fn registered_trader_id(core: &ExecutionAlgorithmCore) -> anyhow::Result<TraderId> {
    DataActorNative::core(core)
        .trader_id()
        .ok_or_else(|| anyhow::anyhow!("ExecutionAlgorithm not registered: trader_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,
        cache::Cache,
        clock::TestClock,
        component::Component,
        enums::ComponentTrigger,
        msgbus::{
            self, TypedHandler,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Set the account_id on the OrderAny before passing it to modify_order/cancel_order (or in tests, use a constructor/factory that assigns it).
  2. Check where the order originated (builder, snapshot, fixture) and ensure account_id is populated at creation time.
  3. If this surfaces in a test like test_required_account_id_errors_when_missing_for_algorithm_event, this error is expected behavior asserting the guard; keep it and fix the fixture instead.
  4. If orders legitimately lack account_id until routing, resolve/assign it earlier in the pipeline so the algorithm always receives fully attributed orders.

Example fix

// before
let order = OrderAny::builder(...).build(); // no account_id
algo.cancel_order(order)?;

// after
let order = OrderAny::builder(...)
    .account_id(account_id) // e.g. AccountId::from("SIM-001")
    .build();
algo.cancel_order(order)?;
Defensive patterns

Strategy: validation

Validate before calling

if order.account_id().is_none() {
    return Err(anyhow::anyhow!(
        "order {} has no account_id; cannot generate modify/cancel event",
        order.client_order_id()
    ));
}

Type guard

fn has_account_id(order: &OrderAny) -> bool {
    order.account_id().is_some()
}

Prevention

When it happens

Trigger: Calling `modify_order` or `cancel_order` on an ExecutionAlgorithm with an `OrderAny` whose account_id was never set (e.g. built via OrderAny builders without `account_id(...)`, or deserialized from fixtures lacking the field).

Common situations: Test fixtures or manually constructed orders missing account_id; orders restored from persistence/migrations created before account_id was mandatory; wiring an algorithm against orders from another subsystem that defers account assignment until routing.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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