nautechsystems/nautilus_trader · error
Cannot create command BatchModifyOrders: quantity, price, an
Error message
Cannot create command BatchModifyOrders: quantity, price, and trigger were either None or the same as existing values for {} What it means
For at least one order in the batch, every supplied update (quantity, price, trigger_price) was either None or already equal to the current value, so the command would be a no-op. The library refuses to emit a BatchModifyOrders command that changes nothing.
Source
Thrown at crates/trading/src/strategy/mod.rs:534
updating = true;
}
}
if let Some(trigger_price) = trigger_price {
if !STOP_ORDER_TYPES.contains(&order.order_type()) {
anyhow::bail!(
"{} orders do not have a STOP trigger price",
order.order_type()
);
}
if Some(*trigger_price) != order.trigger_price() {
updating = true;
}
}
if !updating {
anyhow::bail!(
"Cannot create command BatchModifyOrders: quantity, price, and trigger were \
either None or the same as existing values for {}",
order.client_order_id()
);
}
if order.is_closed() || order.is_pending_cancel() {
anyhow::bail!(
"Cannot create command BatchModifyOrders: state is {:?}, {order:?}",
order.status()
);
}
}
let params = params.filter(|params| !params.is_empty());
let mut modifies = Vec::with_capacity(orders.len());
for (order, (_, quantity, price, trigger_price)) in orders.into_iter().zip(updates) {View on GitHub (pinned to 18893faf8b)
Solutions
- Check that at least one of quantity/price/trigger_price differs from the order's current value before calling
- Skip orders with no effective change: if !updating { continue; } logic at the call site
- Refresh order state from the cache so comparisons use current values
Example fix
// before
strategy.modify_orders(&orders, &updates, None, None).await?;
// after
let effective: Vec<_> = orders.iter().zip(updates.iter())
.filter(|(o, (_, q, p, t))|
q.is_some_and(|q| *q != o.quantity())
|| p.is_some_and(|p| Some(*p) != o.price())
|| t.is_some_and(|t| Some(*t) != o.trigger_price()))
.collect();
if !effective.is_empty() {
strategy.modify_orders(&orders, &updates, None, None).await?;
} Defensive patterns
Strategy: validation
Validate before calling
fn has_effective_change(o: &OrderAny, q: Option<Quantity>, p: Option<Price>, t: Option<Price>) -> bool {
q.is_some_and(|q| q != o.quantity())
|| p.is_some_and(|p| Some(p) != o.price())
|| t.is_some_and(|t| Some(t) != o.trigger_price())
} Prevention
- Compare updates against fresh order state, not stale copies
- Skip orders with no effective change
- Refresh cache reads before computing new values
- Avoid blanket retries after successful modifies
When it happens
Trigger: Calling modify_orders where all Some values match current order state, or all fields are None (e.g. re-running an already-applied modify, or idempotent retry after the first modify succeeded).
Common situations: Idempotent retries after a timeout where the first modify already landed; computing new values from stale cached data; update struct defaults leaving all fields None.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Cannot batch modify empty order list
- Cannot batch modify orders for different instruments: {} vs
- Cannot include emulated or local orders in batch modify
- Cannot create command BatchModifyOrders: state is {:?}, {ord
- Cannot batch cancel empty order list
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/afee878424156b44.
Report an issue: GitHub.