nautechsystems/nautilus_trader · error
Order in list denied: invalid status for {}, expected INITIA
Error message
Order in list denied: invalid status for {}, expected INITIALIZED What it means
Every order in a submitted list must be in OrderStatus::Initialized. If any order in the list has already transitioned (submitted, accepted, modified, etc.), submit_order_list bails naming the offending client_order_id, since a list submit would resend a live/stale order.
Source
Thrown at crates/trading/src/strategy/mod.rs:211
/// or order list submission fails.
fn submit_order_list(
&mut self,
mut orders: Vec<OrderAny>,
position_id: Option<PositionId>,
client_id: Option<ClientId>,
params: Option<Params>,
) -> anyhow::Result<()>
where
Self: StrategyNative,
{
if orders.is_empty() {
log::error!("OrderList denied: no orders to submit");
anyhow::bail!("OrderList denied: no orders to submit");
}
for order in &orders {
if order.status() != OrderStatus::Initialized {
anyhow::bail!(
"Order in list denied: invalid status for {}, expected INITIALIZED",
order.client_order_id()
);
}
}
let first_venue = orders[0].instrument_id().venue;
for order in &orders {
if order.instrument_id().venue != first_venue {
anyhow::bail!(
"OrderList denied: orders must share the same venue; \
expected {first_venue}, found {} on {}",
order.instrument_id().venue,
order.client_order_id(),
);
}
}
View on GitHub (pinned to 18893faf8b)
Solutions
- Filter the list to orders with status INITIALIZED before submitting.
- Create fresh orders via the order factory for retries instead of reusing submitted objects.
- Track which orders were already submitted and exclude them from subsequent lists.
Example fix
// before
self.submit_order_list(OrderList(orders))
// after
fresh = [o for o in orders if o.status == OrderStatus.INITIALIZED]
if fresh:
self.submit_order_list(OrderList(fresh)) Defensive patterns
Strategy: validation
Validate before calling
fresh = [o for o in orders if o.status == OrderStatus.INITIALIZED]
if len(fresh) != len(orders):
self.log.warning(f"dropping {len(orders) - len(fresh)} non-INITIALIZED orders from list") Type guard
def all_initialized(orders) -> bool:
return all(o.status == OrderStatus.INITIALIZED for o in orders) Try / catch
try:
self.submit_order_list(order_list)
except RuntimeError as e:
if "invalid status" in str(e):
self.log.error(f"order list contained submitted orders: {e}")
else:
raise Prevention
- Never reuse order objects after submission; create new ones via the order factory for retries
- Filter batches by status == INITIALIZED immediately before submitting
- Do not cache order objects across strategy restarts or on_start invocations
When it happens
Trigger: Passing an order that was already submitted (or whose submit failed midway and is being retried) inside the orders vector; mixing freshly created orders with previously submitted ones in one list.
Common situations: Retry logic that resubmits the same order objects after a transient error; caching order objects across on_start invocations; replaying a batch that includes live orders.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Order missing ord_status and cannot infer (order_id={}, clie
- Either client_order_id or venue_order_id is required
- generate_order_status_report requires venue_order_id
- generate_order_status_report requires instrument_id
- Cannot add strategy while node is running, add strategies be
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/40f3058c84fd43ef.
Report an issue: GitHub.