nautechsystems/nautilus_trader · error
Order invariant violated: first event must be OrderInitializ
Error message
Order invariant violated: first event must be OrderInitialized
What it means
`OrderAny::init_event` retrieves the first event of the order and asserts it is an `OrderEventAny::Initialized`. A panic here means the internal order invariant — every order's event log starts with `OrderInitialized` — was violated: either the order was constructed without an init event or events were reordered/removed. This is a protected internal invariant, not a user-recoverable error.
Source
Thrown at crates/model/src/orders/any.rs:116
Ok(order)
}
/// Returns a reference to the [`crate::events::OrderInitialized`] event.
///
/// This is always the first event in the order's event list (invariant).
///
/// # Panics
///
/// Panics if the first event is not `OrderInitialized` (violates invariant).
#[must_use]
pub fn init_event(&self) -> &crate::events::OrderInitialized {
match self
.events()
.first()
.expect("Order invariant violated: no events")
{
OrderEventAny::Initialized(init) => init,
_ => panic!("Order invariant violated: first event must be OrderInitialized"),
}
}
/// Assigns the order to the list identified by `id`.
///
/// # Panics
///
/// Panics if the order has no events or its first event is not `OrderInitialized`.
pub fn set_order_list_id(&mut self, id: OrderListId) {
let order: &mut OrderCore = match self {
Self::Limit(order) => order,
Self::LimitIfTouched(order) => order,
Self::Market(order) => order,
Self::MarketIfTouched(order) => order,
Self::MarketToLimit(order) => order,
Self::StopLimit(order) => order,
Self::StopMarket(order) => order,
Self::TrailingStopLimit(order) => order,View on GitHub (pinned to 18893faf8b)
Solutions
- Ensure every OrderAny is created via its constructor (`OrderAny::new`/initialized from an OrderInitialized event) before any other events are pushed.
- When rebuilding event logs, always insert/replay the OrderInitialized event first.
- Check serialization/deserialization code so event order is preserved.
- Use the `set_order_list_id`-style public mutators instead of mutating `events` directly.
Example fix
// before let mut order = OrderAny::test_default(); order.events.clear(); let init = order.init_event(); // panics // after let order = OrderAny::new(init_event, trader_id, strategy_id, account_id); // init first let init = order.init_event();
Defensive patterns
Strategy: type-guard
Validate before calling
fn has_valid_init_event(order: &OrderAny) -> bool {
matches!(order.events().first(), Some(OrderEventAny::Initialized(_)))
} Type guard
fn first_event_is_initialized(order: &OrderAny) -> Option<&OrderInitialized> {
match order.events().first() {
Some(OrderEventAny::Initialized(init)) => Some(init),
_ => None,
}
} Prevention
- Construct orders only via their constructors so OrderInitialized is always the first event
- Never push events into the events vec manually; use the event-application APIs
- Preserve event order in serialization/replay pipelines
When it happens
Trigger: Calling `order.init_event()` on an `OrderAny` whose `events` list is non-empty but does not start with `Initialized` (e.g. manually pushed a Submitted/Filled event first, or deserialized a corrupted event log).
Common situations: Custom event-log reconstruction or replay code appending events out of order; test helpers building orders by pushing events manually; serde deserialization of truncated event histories.
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
- Close command should not be drained
- Flush command should not be drained
- Invalid `OrderEventAny` not `OrderFilled`, was {event:?}
- {FAILED}: {e}
- API key is valid UTF-8
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/afcbd13cd1441ce4.
Report an issue: GitHub.