nautechsystems/nautilus_trader · error

Instrument ID not set

Error message

Instrument ID not set

What it means

OrderTestBuilder::get_instrument_id unwraps the Option<InstrumentId> set via .instrument_id(...). Calling build() without first setting an instrument id panics with 'Instrument ID not set'. The builder treats required fields as panics rather than Result-returning errors.

Source

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

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

    fn get_strategy_id(&self) -> StrategyId {
        self.strategy_id.unwrap_or_else(StrategyId::test_default)
    }

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

    fn get_instrument_id(&self) -> InstrumentId {
        self.instrument_id.expect("Instrument ID not set")
    }

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

    fn get_client_order_id(&self) -> ClientOrderId {
        self.client_order_id
            .unwrap_or_else(ClientOrderId::test_default)
    }

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

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Add .instrument_id(...) to the builder chain before calling build().
  2. Centralize a helper that supplies a default test instrument id.
  3. Check that the value passed is a valid InstrumentId::from("BTCUSDT.BINANCE")-style identifier, not just present.

Example fix

// before
let order = OrderTestBuilder::new(OrderType::Limit).quantity(qty).build();
// after
let order = OrderTestBuilder::new(OrderType::Limit)
    .instrument_id(InstrumentId::from("BTCUSDT.BINANCE"))
    .quantity(qty)
    .build();
Defensive patterns

Strategy: validation

Validate before calling

let mut b = OrderTestBuilder::new(OrderType::Limit);
assert!(instrument_id.is_some(), "instrument_id must be set before build()");
b.instrument_id(instrument_id.unwrap()).build();

Type guard

fn requires_instrument_id(b: &OrderTestBuilder) -> bool { true } // every build() needs it; assert presence in your fixture instead

Try / catch

// builder panics are not catchable panics you should rely on; validate inputs before build
assert!(instrument_id.is_some());

Prevention

When it happens

Trigger: Calling OrderTestBuilder::build() without chaining .instrument_id(InstrumentId) beforehand; the panic is raised inside get_instrument_id during build.

Common situations: Test code copying an existing builder invocation and forgetting the instrument_id line, or refactoring helpers where the instrument id became conditional.

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/e5ed937c88906d8c. Report an issue: GitHub.