nautechsystems/nautilus_trader · error

Unknown trade direction: {}

Error message

Unknown trade direction: {}

What it means

Deribit user-trade websocket messages include a `direction` field that must be "buy" or "sell". `parse_user_trade_msg` maps this to Nautilus `OrderSide`. Any other string means the trade cannot be converted into a FillReport, so the parser bails with this error.

Source

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

            "MT" => "both",
            _ => liq,
        };
        log::warn!(
            "Liquidation trade: {} trade_id={} order_id={} liquidation_side={} direction={} amount={} price={}",
            instrument_id,
            msg.trade_id,
            msg.order_id,
            who,
            msg.direction,
            msg.amount,
            msg.price,
        );
    }

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

    let price_precision = instrument.price_precision();
    let size_precision = instrument.size_precision();

    let last_qty = Quantity::from_decimal_dp(msg.amount, size_precision)?;
    let last_px = Price::from_decimal_dp(msg.price, price_precision)?;

    let liquidity_side = match msg.liquidity.as_str() {
        "M" => LiquiditySide::Maker,
        "T" => LiquiditySide::Taker,
        _ => LiquiditySide::NoLiquiditySide,
    };

    // Get fee currency from the fee_currency field
    let fee_currency = Currency::from(&msg.fee_currency);
    let commission = Money::from_decimal(msg.fee, fee_currency)?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the raw websocket payload to see the actual `direction` value
  2. Normalize the value (trim/lowercase) before parsing
  3. Update the adapter if Deribit changed or extended the direction vocabulary
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

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

Try / catch

match parse_user_trade_msg(&msg, &instrument) {
    Ok(fill) => { /* use fill */ }
    Err(e) => tracing::error!(trade_id = %msg.trade_id, %e, "dropping unparseable trade message"),
}

Prevention

When it happens

Trigger: `parse_user_trade_msg` invoked via `route_user_trades` or `request_fill_reports` with a trade message whose `direction` is not exactly "buy" or "sell" (wrong casing, empty string, unmapped field, or new Deribit value).

Common situations: Deribit adding a new direction value or changing the schema; users replaying recorded/synthetic trade payloads with malformed direction; JSON deserialization bugs mapping the wrong source field into `direction`.

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