nautechsystems/nautilus_trader · error

{FAILED}: {e}

Error message

{FAILED}: {e}

What it means

OrderTestBuilder::build panics with `Condition failed: {e}` when constructing an OrderAny::TrailingStopMarket via TrailingStopMarketOrder::new_checked returns an OrderError. The builder deliberately uses `new_checked` and converts the Err into a panic (unwrap_or_else), because a malformed order spec is a programmer error rather than a recoverable runtime condition. The inner error comes from nautilus correctness checks (crates/core/src/correctness.rs, `FAILED = "Condition failed"`) and OrderError invariants (crates/model/src/orders/mod.rs).

Source

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

                    self.get_time_in_force(),
                    self.get_expire_time(),
                    self.get_reduce_only(),
                    self.get_quote_quantity(),
                    self.get_display_qty(),
                    self.get_emulation_trigger(),
                    self.get_trigger_instrument_id(),
                    self.get_contingency_type(),
                    self.get_order_list_id(),
                    self.get_linked_order_ids(),
                    self.get_parent_order_id(),
                    self.get_exec_algorithm_id(),
                    self.get_exec_algorithm_params(),
                    self.get_exec_spawn_id(),
                    self.get_tags(),
                    self.get_init_id(),
                    self.get_ts_init(),
                )
                .unwrap_or_else(|e| panic!("{FAILED}: {e}")),
            ),
            OrderType::TrailingStopLimit => OrderAny::TrailingStopLimit(
                TrailingStopLimitOrder::new_checked(
                    self.get_trader_id(),
                    self.get_strategy_id(),
                    self.get_instrument_id(),
                    self.get_client_order_id(),
                    self.get_side(),
                    self.get_quantity(),
                    self.get_activation_price(),
                    self.price,
                    self.trigger_price,
                    self.get_trigger_type(),
                    self.get_limit_offset(),
                    self.get_trailing_offset(),
                    self.get_trailing_offset_type(),
                    self.get_time_in_force(),
                    self.get_expire_time(),

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Read the inner `{e}` OrderError message in the panic text; it names the exact failed check (e.g. 'display_qty exceeds quantity', 'GTD requires expire_time').
  2. Fix the builder spec: set a positive Quantity, ensure display_qty <= quantity, and supply expire_time when time_in_force is GTD.
  3. Ensure a valid OrderSide (Buy/Sell) is set on the builder.
  4. If the failing values come from external config, validate them before calling build(), or switch to the order type's new_checked API to handle the error instead of panicking.

Example fix

// before
OrderTestBuilder::new(OrderType::TrailingStopMarket)
    .quantity(Quantity::from(0))
    .build()
// after
OrderTestBuilder::new(OrderType::TrailingStopMarket)
    .side(OrderSide::Buy)
    .quantity(Quantity::from(100))
    .build()
Defensive patterns

Strategy: validation

Validate before calling

fn valid_tsm_spec(qty: Quantity, display_qty: Option<Quantity>, tif: TimeInForce, expire_time: Option<UnixNanos>) -> Result<(), String> {
    if qty.raw == 0 { return Err("quantity must be positive".into()); }
    if let Some(dq) = display_qty { if dq > qty { return Err("display_qty exceeds quantity".into()); } }
    if tif == TimeInForce::Gtd && expire_time.map_or(true, |t| t.as_u64() == 0) { return Err("GTD requires expire_time".into()); }
    Ok(())
}

Type guard

if builder_spec.quantity.is_zero() || builder_spec.side == OrderSide::NoOrderSide { return; }

Prevention

When it happens

Trigger: Calling OrderTestBuilder().build(OrderType::TrailingStopMarket) with a spec that fails validation: quantity not positive, display_qty greater than quantity, TimeInForce::Gtd with a None or zero expire_time, or an OrderInitialized invariant violation (e.g. side NoOrderSide, invalid combination of contingency/linked fields). For TrailingStopMarket specifically the trigger may be unset (activate-at-market path) but trailing_offset/type and activation checks must still pass.

Common situations: Test fixtures reusing a builder template across order types and forgetting to set expire_time for GTD; setting display_qty from config without clamping to quantity; constructing orders from deserialized strategy configs with zero quantity; passing OrderSide default/NoOrderSide from an unvalidated enum conversion.

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


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