nautechsystems/nautilus_trader · error

Cannot include emulated or local orders in batch cancel

Error message

Cannot include emulated or local orders in batch cancel

What it means

Batch cancel only supports orders routed directly to the venue. Emulated or active-local orders are managed by the execution emulator/risk engine, so they are rejected from BatchCancelOrders commands.

Source

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

                        .try_order_owned(id)
                        .map_err(|e| anyhow::anyhow!("Cannot cancel order: {e}"))
                })
                .collect::<Result<_, _>>()?
        };

        let instrument_id = orders[0].instrument_id();

        for order in &orders {
            if order.instrument_id() != instrument_id {
                anyhow::bail!(
                    "Cannot batch cancel orders for different instruments: {} vs {}",
                    instrument_id,
                    order.instrument_id()
                );
            }

            if order.is_emulated() || order.is_active_local() {
                anyhow::bail!("Cannot include emulated or local orders in batch cancel");
            }
        }

        let mut cancels = Vec::with_capacity(orders.len());

        for order in orders {
            if !self.mark_order_pending_cancel(&order)? {
                continue;
            }

            cancels.push(CancelOrder::new(
                trader_id,
                client_id,
                strategy_id,
                instrument_id,
                order.client_order_id(),
                order.venue_order_id(),
                UUID4::new(),

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Exclude emulated/active-local orders from the batch and cancel them individually via cancel_order
  2. Filter: if order.is_emulated() || order.is_active_local() { strategy.cancel_order(...) } else { include in batch }
  3. Adjust emulation config if direct venue cancels should cover these orders

Example fix

// before
strategy.cancel_orders(&ids, instrument_id, None, None).await?;
// after
let (direct, emulated): (Vec<_>, Vec<_>) = orders.iter()
    .partition(|o| !o.is_emulated() && !o.is_active_local());
if !direct.is_empty() {
    strategy.cancel_orders(&ids_for(direct), instrument_id, None, None).await?;
}
for o in &emulated {
    strategy.cancel_order(o.client_order_id(), None).await?;
}
Defensive patterns

Strategy: validation

Validate before calling

let direct: Vec<_> = ids.iter()
    .filter(|id| !cache.order(id).map(|o| o.is_emulated() || o.is_active_local()).unwrap_or(false))
    .collect();

Type guard

fn batch_cancel_eligible(o: &OrderAny) -> bool { !o.is_emulated() && !o.is_active_local() }

Prevention

When it happens

Trigger: Passing a client_order_id whose resolved order has `is_emulated()` or `is_active_local()` true to `cancel_orders`.

Common situations: Emulated contingent orders on venues without native support; blanket 'cancel all working orders' sweeps that include emulated orders; mixing direct and emulated orders collected from the cache.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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