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
- 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').
- Fix the builder spec: set a positive Quantity, ensure display_qty <= quantity, and supply expire_time when time_in_force is GTD.
- Ensure a valid OrderSide (Buy/Sell) is set on the builder.
- 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
- Always set side, a positive quantity, and every field the target order type requires on OrderTestBuilder
- Supply expire_time whenever time_in_force is GTD
- Clamp display_qty to <= quantity before building
- Prefer new_checked variants and handle OrderError when values come from untrusted input
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.