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

  1. Set the protection price when constructing MarketOrderWithProtection orders if downstream code reads limit_px.
  2. Skip MarketOrderWithProtection orders (or handle their price as Option) in generic limit_px loops.
  3. 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

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


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/8c6bf3d7f29b5b25. Report an issue: GitHub.