nautechsystems/nautilus_trader · error

Not a conditional order type: {order_type:?}

Error message

Not a conditional order type: {order_type:?}

What it means

conditional_order_to_algo_type maps Nautilus conditional order types (StopMarket, StopLimit, MarketIfTouched, LimitIfTouched to Trigger; TrailingStopMarket to MoveOrderStop) to OKX algo order types; any other OrderType falls through to the wildcard arm and is rejected, because plain orders must not be routed through the algo-order API.

Source

Thrown at crates/adapters/okx/src/common/enums.rs:1398

/// Returns whether an order type requires the advance algo cancel endpoint.
pub fn is_advance_algo_order(order_type: OrderType) -> bool {
    OKX_ADVANCE_ALGO_ORDER_TYPES.contains(&order_type)
}

/// Converts Nautilus conditional order types to OKX algo order type.
///
/// # Errors
///
/// Returns an error if the provided `order_type` is not a conditional order type.
pub fn conditional_order_to_algo_type(order_type: OrderType) -> anyhow::Result<OKXAlgoOrderType> {
    match order_type {
        OrderType::StopMarket
        | OrderType::StopLimit
        | OrderType::MarketIfTouched
        | OrderType::LimitIfTouched => Ok(OKXAlgoOrderType::Trigger),
        OrderType::TrailingStopMarket => Ok(OKXAlgoOrderType::MoveOrderStop),
        _ => anyhow::bail!("Not a conditional order type: {order_type:?}"),
    }
}

/// Represents the state of an algo (trigger/OCO/conditional) order on OKX.
#[derive(
    Copy,
    Clone,
    Debug,
    Display,
    PartialEq,
    Eq,
    Hash,
    AsRefStr,
    EnumIter,
    EnumString,
    Serialize,
    Deserialize,
)]

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Route only conditional types (StopMarket, StopLimit, MarketIfTouched, LimitIfTouched, TrailingStopMarket) through the algo-order path
  2. Submit plain Limit/Market orders via the normal place_order path
  3. Extend the mapping if a new conditional type (e.g. TrailingStopLimit) needs OKX algo support

Example fix

// before
submit_algo_order(order_factory.limit(...)) // non-conditional type
// after
submit_order(order_factory.limit(...))
Defensive patterns

Strategy: type-guard

Validate before calling

// Rust
fn is_okx_conditional(order_type: OrderType) -> bool {
    matches!(order_type,
        OrderType::StopMarket | OrderType::StopLimit
        | OrderType::MarketIfTouched | OrderType::LimitIfTouched
        | OrderType::TrailingStopMarket)
}
assert!(is_okx_conditional(order.order_type()), "route plain orders via submit_order");

Type guard

fn is_conditional(t: OrderType) -> bool {
    matches!(t, OrderType::StopMarket | OrderType::StopLimit
        | OrderType::MarketIfTouched | OrderType::LimitIfTouched
        | OrderType::TrailingStopMarket)
}

Prevention

When it happens

Trigger: Calling submit_algo_order / place_algo_order_with_domain_types with a non-conditional OrderType such as OrderType::Limit, OrderType::Market, or an unmapped type like TrailingStopLimit.

Common situations: Misrouting regular orders into the algo submission path; using an order type the adapter has not mapped; factory code choosing order types dynamically.

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