nautechsystems/nautilus_trader · error

Unknown order direction: {}

Error message

Unknown order direction: {}

What it means

Deribit user-order websocket messages include a `direction` field that must be "buy" or "sell". `parse_user_order_msg` maps this to Nautilus `OrderSide::Buy`/`Sell`. Any other string means the message cannot be translated into an OrderStatusReport, so the parse fails with this error.

Source

Thrown at crates/adapters/deribit/src/websocket/parse.rs:721

/// Parses a Deribit user order message into a Nautilus `OrderStatusReport`.
///
/// # Errors
///
/// Returns an error if the order data cannot be parsed.
pub fn parse_user_order_msg(
    msg: &DeribitOrderMsg,
    instrument: &InstrumentAny,
    account_id: AccountId,
    ts_init: UnixNanos,
) -> anyhow::Result<OrderStatusReport> {
    let instrument_id = instrument.id();
    let venue_order_id = VenueOrderId::new(&msg.order_id);

    let order_side = match msg.direction.as_str() {
        "buy" => OrderSide::Buy,
        "sell" => OrderSide::Sell,
        _ => anyhow::bail!("Unknown order direction: {}", msg.direction),
    };

    // Map Deribit order type to Nautilus
    let order_type = parse_deribit_order_type(&msg.order_type);

    // Deribit supports: good_til_cancelled, good_til_day, fill_or_kill, immediate_or_cancel
    let time_in_force = match msg.time_in_force.as_str() {
        "good_til_cancelled" => TimeInForce::Gtc,
        "good_til_day" => TimeInForce::Gtd,
        "fill_or_kill" => TimeInForce::Fok,
        "immediate_or_cancel" => TimeInForce::Ioc,
        other => {
            log::warn!("Unknown time_in_force '{other}', defaulting to GTC");
            TimeInForce::Gtc
        }
    };

    // Map Deribit order state to Nautilus status

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Log the raw message and inspect the actual `direction` value to see why it deviates
  2. Normalize direction to lowercase "buy"/"sell" before passing the message to the parser
  3. Update/patch the adapter if Deribit introduced a new direction value; otherwise treat the message as unparseable and skip it

Example fix

// before
let msg = DeribitOrderMsg { direction: "Buy".to_string(), .. };
let report = parse_user_order_msg(&msg, &instrument)?; // errors
// after
let msg = DeribitOrderMsg { direction: msg.direction.to_lowercase(), .. };
let report = parse_user_order_msg(&msg, &instrument)?;
Defensive patterns

Strategy: validation

Validate before calling

fn is_valid_direction(d: &str) -> bool { matches!(d, "buy" | "sell") }

Type guard

fn is_valid_direction(d: &str) -> bool { matches!(d, "buy" | "sell") }

Try / catch

match parse_user_order_msg(&msg, &instrument) {
    Ok(report) => { /* use report */ }
    Err(e) => tracing::error!(order_id = %msg.order_id, %e, "dropping unparseable order message"),
}

Prevention

When it happens

Trigger: Calling `parse_user_order_msg` (directly or via `process_raw_message`/`generate_order_status_report`) with an order message whose `direction` is neither "buy" nor "sell" — e.g. an empty string, a changed/renamed field from Deribit, or a hand-crafted test payload.

Common situations: Deribit protocol changes or new order message variants; bugs in locally deserialized JSON (wrong field mapped to `direction`); constructing synthetic Deribit messages in tests or simulators with incorrect casing like "Buy".

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