nautechsystems/nautilus_trader · error

Cannot include emulated or local orders in batch modify

Error message

Cannot include emulated or local orders in batch modify

What it means

Batch modify only supports orders that are routed directly to the venue. Orders flagged as emulated (locally emulated contingent orders) or active-local are rejected because their lifecycle is managed by the risk engine/execution emulator, not a single venue command.

Source

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

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

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

        for (order, (_, quantity, price, trigger_price)) in orders.iter().zip(updates.iter()) {
            if order.instrument_id() != instrument_id {
                anyhow::bail!(
                    "Cannot batch modify 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 modify");
            }

            let mut updating = false;

            if quantity.is_some_and(|q| q != order.quantity()) {
                updating = true;
            }

            if let Some(price) = price {
                if !LIMIT_ORDER_TYPES.contains(&order.order_type()) {
                    anyhow::bail!("{} orders do not have a LIMIT price", order.order_type());
                }

                if Some(*price) != order.price() {
                    updating = true;
                }
            }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Exclude emulated and active-local orders from the batch and modify them individually via modify_order
  2. Check `order.is_emulated() || order.is_active_local()` and route those orders through per-order handling
  3. Reconsider emulation configuration if batch ops on emulated orders are required

Example fix

// before
let batch: Vec<&OrderAny> = open_orders.iter().collect();
strategy.modify_orders(&batch, &updates, None, None).await?;
// after
let batch: Vec<&OrderAny> = open_orders.iter()
    .filter(|o| !o.is_emulated() && !o.is_active_local())
    .collect();
for o in open_orders.iter().filter(|o| o.is_emulated() || o.is_active_local()) {
    strategy.modify_order(o, quantity, price, trigger_price, None).await?;
}
strategy.modify_orders(&batch, &updates, None, None).await?;
Defensive patterns

Strategy: validation

Validate before calling

let batch: Vec<_> = orders.iter()
    .filter(|o| !o.is_emulated() && !o.is_active_local())
    .collect();

Type guard

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

Prevention

When it happens

Trigger: Including an order where `order.is_emulated()` or `order.is_active_local()` is true in the batch passed to `modify_orders`.

Common situations: Using emulation for contingent/bracket orders on venues without native support, then attempting a batch amend; accidentally mixing emulated and direct orders in one batch; submitting a batch modify to a venue (e.g. Binance) that doesn't support batch amend for emulated positions.

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/5dc6568cf75f222d. Report an issue: GitHub.