nautechsystems/nautilus_trader · error
OrderFactory::create_list requires non-empty orders
Error message
OrderFactory::create_list requires non-empty orders
What it means
OrderFactory::create_list builds an OrderList from a slice of orders and derives the shared instrument_id/venue from the first order. It panics when the slice is empty; the public wrapper filters out empty input and mixed venues before reaching this constructor, so hitting it means the guard was bypassed.
Source
Thrown at crates/common/src/factories/order.rs:1092
/// Creates a new [`OrderList`] from the given orders, generating a fresh
/// order list ID and propagating it back to each order.
///
/// All orders must share the same venue; the caller is responsible for
/// passing orders with the factory's `strategy_id`. The returned list's
/// invariants are checked by [`OrderList::validate`] at submission time.
///
/// # Panics
///
/// Panics if `orders` is empty or if orders span more than one venue.
/// Callers are expected to guard non-empty input; `Strategy::submit_order_list`
/// filters out the empty case and bails on mixed venues before reaching
/// this constructor.
#[must_use]
pub fn create_list(&mut self, orders: &mut [OrderAny], ts_init: UnixNanos) -> OrderList {
let instrument_id = orders
.first()
.expect("OrderFactory::create_list requires non-empty orders")
.instrument_id();
let venue = instrument_id.venue;
for order in orders.iter() {
assert!(
order.instrument_id().venue == venue,
"OrderFactory::create_list requires all orders to share the same venue; \
expected {venue}, found {} on {}",
order.instrument_id().venue,
order.client_order_id(),
);
}
let order_list_id = self.generate_order_list_id();
let order_ids: Vec<ClientOrderId> = orders.iter().map(OrderAny::client_order_id).collect();
for order in orders.iter_mut() {
order.set_order_list_id(order_list_id);View on GitHub (pinned to 18893faf8b)
Solutions
- Check !orders.is_empty() before calling create_list
- Filter upstream so empty lists short-circuit and return an empty/None result instead
- If mixing venues is possible, group orders by venue first (create_list also asserts a single venue)
- Prefer the public wrapper that documents the empty-case filtering
Example fix
// before let list = factory.create_list(&mut orders, ts_init); // after assert!(!orders.is_empty(), "no orders to submit"); let list = factory.create_list(&mut orders, ts_init);
Defensive patterns
Strategy: validation
Validate before calling
if orders.is_empty() {
return Ok(OrderList::default()); // or early-return your own error
}
let venue = orders[0].instrument_id().venue;
if orders.iter().any(|o| o.instrument_id().venue != venue) {
return Err("mixed venues in create_list input".into());
} Type guard
fn non_empty(orders: &[OrderAny]) -> Option<&[OrderAny]> {
if orders.is_empty() { None } else { Some(orders) }
} Try / catch
// Panic is not catchable; guard before the call assert!(!orders.is_empty(), "create_list requires at least one order"); let list = factory.create_list(&mut orders, ts_init);
Prevention
- Early-return on empty order collections after filtering
- Group orders by venue before building an OrderList (single venue required)
- Centralize order-list construction so the emptiness check lives in one place
When it happens
Trigger: Calling create_list with an empty orders slice directly (or via a path that skips the emptiness check), then reading orders.first() -> None -> panic.
Common situations: Building order lists from a dynamically filtered collection that ended up empty (e.g. all orders filtered out); tests constructing lists directly; upstream code passing Vec::new().
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- {e}
- Chunk should have at least one element to encode
- OrderList::from_orders requires non-empty orders
- in-flight mutex poisoned
- wallet balance mutex poisoned
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/4670c021e8c04faa.
Report an issue: GitHub.