nautechsystems/nautilus_trader · error

Invalid `OrderType` {order_type} for trailing stop calculati

Error message

Invalid `OrderType` {order_type} for trailing stop calculation

What it means

trailing_stop_calculate only supports trailing stop orders; the check `matches!(order_type, TrailingStopMarket | TrailingStopLimit)` guards the offset/trigger math that follows. Passing any other OrderType means the caller routed a non-trailing order into a trailing-stop-only code path, so the library refuses to compute a trailing stop price for it.

Source

Thrown at crates/execution/src/trailing.rs:54

/// - the order type, trigger type, or trailing offset type is invalid.
/// - the order lacks a required trigger, trailing offset, trailing offset type, or limit offset.
/// - the calculated price cannot be represented as a [`Price`].
pub fn trailing_stop_calculate(
    price_increment: Price,
    trigger_px: Option<Price>,
    order: &OrderAny,
    bid: Option<Price>,
    ask: Option<Price>,
    last: Option<Price>,
) -> anyhow::Result<(Option<Price>, Option<Price>)> {
    let order_side = order.order_side();
    let order_type = order.order_type();

    if !matches!(
        order_type,
        OrderType::TrailingStopMarket | OrderType::TrailingStopLimit
    ) {
        anyhow::bail!("Invalid `OrderType` {order_type} for trailing stop calculation");
    }

    // Seed from the current trigger only (never the activation price): when the trigger has
    // not yet materialized it stays `None` here so the offset candidate below becomes the
    // initial trigger on the first update (matches v1 `TrailingStopCalculator`).
    let mut trigger_price = trigger_px.or(order.trigger_price());

    let mut limit_price = if order_type == OrderType::TrailingStopLimit {
        order.price()
    } else {
        None
    };

    let trigger_type = order
        .trigger_type()
        .ok_or_else(|| anyhow::anyhow!("Missing `TriggerType` for trailing stop calculation"))?;
    let trailing_offset = order.trailing_offset().ok_or_else(|| {
        anyhow::anyhow!("Missing `trailing_offset` for trailing stop calculation")

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure the order is created as OrderType::TrailingStopMarket or OrderType::TrailingStopLimit before calling trailing_stop_calculate.
  2. In the caller, branch on order.order_type() and route non-trailing orders to a different update path.
  3. Check the order factory / venue adapter mapping that produced the order for a mislabeled order type.

Example fix

// before
let order = factory.stop_market(...);
update_trailing_stop_order(&order, ...)?; // bails: invalid OrderType
// after
let order = factory.trailing_stop_market(...);
update_trailing_stop_order(&order, ...)?;
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_trailing(order: &dyn Order) -> anyhow::Result<()> {
    matches!(order.order_type(), OrderType::TrailingStopMarket | OrderType::TrailingStopLimit)
        .then_some(())
        .ok_or_else(|| anyhow::anyhow!("order {} is not a trailing stop", order.client_order_id()))
}

Type guard

fn is_trailing_stop(order_type: OrderType) -> bool {
    matches!(order_type, OrderType::TrailingStopMarket | OrderType::TrailingStopLimit)
}

Prevention

When it happens

Trigger: Calling trailing_stop_calculate (directly or via update_trailing_stop_order) with an order whose order_type() is e.g. StopMarket, StopLimit, Limit, or MarketOrder instead of TrailingStopMarket/TrailingStopLimit.

Common situations: An order factory or strategy code emits a plain StopMarket but then the risk/trailing module tries to update it as trailing; refactoring changed the constructed order type; a bug passes a parsed order of the wrong type from a venue adapter.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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