nautechsystems/nautilus_trader · error · anyhow::Error

Missing required field: order_id

Error message

Missing required field: order_id

What it means

Field guard in convert_ws_fill_to_http: the WebSocket fill message lacks the order_id field, which is mandatory to correlate the fill with a Nautilus order, so conversion to the HTTP fill model fails.

Source

Thrown at crates/adapters/dydx/src/websocket/parse.rs:358

    let created_at_height: u64 = ws_fill
        .created_at_height
        .as_ref()
        .map(|s| s.parse())
        .transpose()
        .context("Failed to parse created_at_height")?
        .unwrap_or(0);

    let client_metadata: u32 = ws_fill
        .client_metadata
        .as_ref()
        .ok_or_else(|| anyhow::anyhow!("Missing required field: client_metadata"))?
        .parse()
        .context("Failed to parse client_metadata")?;

    let order_id = ws_fill
        .order_id
        .clone()
        .ok_or_else(|| anyhow::anyhow!("Missing required field: order_id"))?;

    let created_at = ws_fill
        .created_at
        .parse::<Timestamp>()
        .context("Failed to parse created_at")?;

    Ok(Fill {
        id: ws_fill.id.clone(),
        side: ws_fill.side,
        liquidity: ws_fill.liquidity,
        fill_type: ws_fill.fill_type,
        market: ws_fill.market,
        market_type: ws_fill.market_type.unwrap_or(DydxTickerType::Perpetual),
        price,
        size,
        fee,
        created_at,
        created_at_height,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the raw WS payload to confirm the exchange really omitted order_id
  2. Upgrade the adapter/exchange SDK to a version matching the current dYdX proto schema
  3. Skip fills without order_id if they are special fill types irrelevant to order tracking
  4. Report the malformed payload to the exchange/adapter maintainers if it persists

Example fix

// before
let order_id = ws_fill.order_id.clone().ok_or_else(|| anyhow!("Missing required field: order_id"))?;
// after
let Some(order_id) = ws_fill.order_id.clone() else { tracing::warn!("fill missing order_id, skipping"); return Ok(None) };
Defensive patterns

Strategy: validation

Validate before calling

if ws_fill.order_id.is_none() {
    eprintln!("fill missing order_id; cannot attribute to an order");
    return;
}

Type guard

fn has_order_id(f: &WsFill) -> bool {
    f.order_id.as_deref().map(|s| !s.is_empty()).unwrap_or(false)
}

Try / catch

match parse_ws_fill_report(...) {
    Err(e) if e.to_string().contains("order_id") => {
        warn!("dropping fill with missing order_id");
    }
    Err(e) => return Err(e),
    Ok(r) => handle(r),
}

Prevention

When it happens

Trigger: Receiving a WebSocket fill event with a null/missing order_id — malformed exchange messages, liquidation/liquidations-style fills with unusual payloads, or API schema changes.

Common situations: Exchange incidents producing incomplete fill payloads; new dYdX fill types (e.g. liquidations) not carrying order_id; version mismatches between adapter expectations and live proto schema.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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