nautechsystems/nautilus_trader · error
No price for order
Error message
No price for order
What it means
OrderAny::limit_px on MarketOrderWithProtection variants unwraps protection_price, which is optional; if no protection price was supplied when the order was created, the call panics with 'No price for order'.
Source
Thrown at crates/model/src/orders/any.rs:322
}
impl LimitOrderAny {
/// Returns the limit price for this order.
///
/// # Panics
///
/// Panics if the `MarketToLimit` order price is not set.
#[must_use]
pub fn limit_px(&self) -> Price {
match self {
Self::Limit(order) => order.price,
Self::MarketToLimit(order) => order.price.expect("MarketToLimit order price not set"),
Self::StopLimit(order) => order.price,
Self::TrailingStopLimit(order) => {
order.price.expect("TrailingStopLimit order price not set")
}
Self::MarketOrderWithProtection(order) => {
order.protection_price.expect("No price for order")
}
}
}
}
impl PartialEq for LimitOrderAny {
fn eq(&self, rhs: &Self) -> bool {
match self {
Self::Limit(order) => order.client_order_id == rhs.client_order_id(),
Self::MarketToLimit(order) => order.client_order_id == rhs.client_order_id(),
Self::StopLimit(order) => order.client_order_id == rhs.client_order_id(),
Self::TrailingStopLimit(order) => order.client_order_id == rhs.client_order_id(),
Self::MarketOrderWithProtection(order) => {
order.client_order_id == rhs.client_order_id()
}
}
}
}View on GitHub (pinned to 18893faf8b)
Solutions
- Set the protection price when constructing MarketOrderWithProtection orders if downstream code reads limit_px.
- Skip MarketOrderWithProtection orders (or handle their price as Option) in generic limit_px loops.
- Use a price accessor that returns Option<Price> instead of the panicking limit_px.
Example fix
// before
let px = order.limit_px(); // panics when protection_price is None
// after
if matches!(order, OrderAny::MarketOrderWithProtection(_)) { continue; } // no price to report
let px = order.limit_px(); Defensive patterns
Strategy: type-guard
Validate before calling
let px = match &order {
OrderAny::MarketOrderWithProtection(o) => o.protection_price,
_ => Some(order.limit_px()),
}; Type guard
fn order_price_opt(order: &OrderAny) -> Option<Price> {
match order {
OrderAny::MarketOrderWithProtection(o) => o.protection_price,
OrderAny::MarketToLimit(o) => o.price,
OrderAny::TrailingStopLimit(o) => o.price,
_ => Some(order.limit_px()),
}
} Try / catch
// skip or default instead of calling limit_px on price-less market orders let px = order_price_opt(&order).unwrap_or_default();
Prevention
- Do not call limit_px uniformly on all order variants in reporting loops.
- Set protection_price at construction when downstream code expects a price.
- Filter out price-less order types (Market, MarketOrderWithProtection) before price aggregation.
When it happens
Trigger: Calling OrderAny::limit_px() on an OrderAny::MarketOrderWithProtection that was built without .protection_price (or equivalent) set.
Common situations: Generic price-reporting code that calls limit_px on every order in a cache, where market orders with protection legitimately may have no price.
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
- MarketToLimit order price not set
- TrailingStopLimit order price not set
- Invalid order side: {e}
- in-flight mutex poisoned
- wallet balance mutex poisoned
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/8c6bf3d7f29b5b25.
Report an issue: GitHub.