nautechsystems/nautilus_trader · error
Python on_order_list failed: {e}
Error message
Python on_order_list failed: {e} What it means
DataActor command execution wraps the Python on_order_list callback; an exception raised inside the user's Python on_order_list handler is converted into this anyhow error by execute_exec_algorithm_command. It means the exec algorithm failed while processing a submitted order list, aborting the SubmitOrderList command.
Source
Thrown at crates/common/src/python/actor.rs:269
if self.core.config.log_commands {
let id = self.core.actor_id;
log::info!("{id} {RECV}{CMD} {command}");
}
if self.core.state() != ComponentState::Running {
return Ok(());
}
match command {
TradingCommand::SubmitOrder(cmd) => {
let order = DataActor::cache(self).try_order(&cmd.client_order_id)?;
self.dispatch_on_order(order)
.map_err(|e| anyhow::anyhow!("Python on_order failed: {e}"))
}
TradingCommand::SubmitOrderList(cmd) => {
let orders = self.orders_for_list(&cmd.order_list)?;
self.dispatch_on_order_list(cmd.order_list.clone(), orders)
.map_err(|e| anyhow::anyhow!("Python on_order_list failed: {e}"))
}
_ => {
log::warn!("Unhandled command type: {command}");
Ok(())
}
}
}
fn orders_for_list(&self, order_list: &OrderList) -> anyhow::Result<Vec<OrderAny>> {
let cache = DataActor::cache(self);
let mut orders = Vec::with_capacity(order_list.client_order_ids.len());
for client_order_id in &order_list.client_order_ids {
orders.push(cache.try_order(client_order_id)?);
}
Ok(orders)
}View on GitHub (pinned to 18893faf8b)
Solutions
- Inspect the chained '{e}' cause for the original Python exception inside on_order_list
- Make on_order_list defensive: skip/handle orders missing from cache rather than assuming completeness
- Unit-test on_order_list with partially filled or partially denied order lists
- Update handler logic to the current order-list API if upgrading from an older Nautilus version
Example fix
# before
def on_order_list(self, order_list):
total = sum(o.quantity for o in self.orders[o.order_list_id]) # KeyError
# after
def on_order_list(self, order_list):
orders = self.orders.get(order_list.order_list_id, [])
total = sum(o.quantity for o in orders)
if not orders:
self.log.warning("No cached orders for list")
return Defensive patterns
Strategy: try-catch
Validate before calling
def check_order_list_resolved(order_list) -> bool:
cached = [self.cache.order(oid) for oid in order_list.order_ids()]
return all(o is not None for o in cached) and len(cached) > 0 Type guard
def has_all_orders(self, order_list) -> bool:
return all(
self.cache.order(cid) is not None
for cid in order_list.order_ids()
) Try / catch
def on_order_list(self, order_list):
try:
self._handle_order_list(order_list)
except Exception as e:
self.log.exception(f"on_order_list failed for {order_list.order_list_id}: {e}") Prevention
- Never assume every order in a list is cached or filled; filter defensively
- Write unit tests for partial fills, denials, and cancels within order lists
- Avoid stateful assumptions (dicts keyed by list id) that break when lists arrive out of order
- Keep list-handling logic independent of list size
When it happens
Trigger: TradingCommand::SubmitOrderList is executed, orders_for_list resolves the list's orders from cache, and dispatch_on_order_list invokes the Python on_order_list override which raises (e.g. index/attribute errors, missing order in the resolved set).
Common situations: Python exec algorithm assumes all orders of an order list are present or in a specific state, divides by quantity sums that can be zero, or was written for a single order and mishandles list input after a version change.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Python on_order failed: {e}
- Python on_signal failed: {e}
- Python on_queue_state failed: {e}
- Python on_socket_state failed: {e}
- Python on_instrument failed: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/ff08e4fc055168ac.
Report an issue: GitHub.