nautechsystems/nautilus_trader · error

Price not set

Error message

Price not set

What it means

A builder-invariant panic via Option::expect: OrderBuilder::build was invoked without price() having been called, so the required Price field is None. It indicates programmer error — an incomplete order definition — not a recoverable runtime condition; callers must set price before build.

Source

Thrown at crates/model/src/orders/builder.rs:196

    // ----------- Quantity ----------
    pub fn quantity(&mut self, quantity: Quantity) -> &mut Self {
        self.quantity = Some(quantity);
        self
    }

    fn get_quantity(&self) -> Quantity {
        self.quantity.expect("Order quantity not set")
    }

    // ----------- Price ----------
    pub fn price(&mut self, price: Price) -> &mut Self {
        self.price = Some(price);
        self
    }

    fn get_price(&self) -> Price {
        self.price.expect("Price not set")
    }

    // ----------- TriggerPrice ----------
    pub fn trigger_price(&mut self, trigger_price: Price) -> &mut Self {
        self.trigger_price = Some(trigger_price);
        self
    }

    fn get_trigger_price(&self) -> Price {
        self.trigger_price.expect("Trigger price not set")
    }

    // ----------- ActivationPrice ----------
    pub fn activation_price(&mut self, activation_price: Price) -> &mut Self {
        self.activation_price = Some(activation_price);
        self
    }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Add .price(Price::from(...)) to the builder chain before build().
  2. Only omit .price for price-less order types (Market).
  3. Use a fixture function that builds priced orders with sensible defaults.

Example fix

// before
let order = OrderTestBuilder::new(OrderType::Limit).instrument_id(id).quantity(qty).build();
// after
let order = OrderTestBuilder::new(OrderType::Limit)
    .instrument_id(id)
    .quantity(qty)
    .price(Price::from("50000.00"))
    .build();
Defensive patterns

Strategy: validation

Validate before calling

if matches!(order_type, OrderType::Limit | OrderType::StopLimit | OrderType::TrailingStopLimit | OrderType::MarketToLimit) {
    assert!(price.is_some(), "price required for {:?}", order_type);
}
builder.price(price.unwrap()).build();

Type guard

fn order_type_needs_price(t: OrderType) -> bool {
    matches!(t, OrderType::Limit | OrderType::StopLimit | OrderType::TrailingStopLimit | OrderType::MarketToLimit)
}

Try / catch

// check order type before build
assert!(price.is_some() || !order_type_needs_price(order_type));

Prevention

When it happens

Trigger: Building a Limit/StopLimit/TrailingStopLimit order via OrderTestBuilder without chaining .price(Price) before build().

Common situations: Converting a market-order test builder to a limit order without adding the price line, or a parametrized test where the price branch was not supplied.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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