nautechsystems/nautilus_trader · error · anyhow::Error

Missing required field: client_metadata

Error message

Missing required field: client_metadata

What it means

Converting a dYdX WebSocket order message to the HTTP order shape requires client_metadata, which encodes the Nautilus client order ID (parsed as u32). If the ws_order.client_metadata field is absent (None), the converter cannot build an order ID and throws this error.

Source

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

        .unwrap_or(Decimal::ZERO);

    // Saturate to zero if total_filled exceeds size (edge case: rounding or partial fills)
    let remaining_size = (size - total_filled).max(Decimal::ZERO);

    let price: Decimal = ws_order.price.parse().context("Failed to parse price")?;

    let created_at_height: u64 = ws_order
        .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_order
        .client_metadata
        .as_ref()
        .ok_or_else(|| anyhow::anyhow!("Missing required field: client_metadata"))?
        .parse()
        .context("Failed to parse client_metadata")?;

    let order_flags: u32 = ws_order
        .order_flags
        .parse()
        .context("Failed to parse order_flags")?;

    let good_til_block = ws_order
        .good_til_block
        .as_ref()
        .and_then(|s| s.parse::<u64>().ok());

    let good_til_block_time = ws_order
        .good_til_block_time
        .as_ref()
        .and_then(|s| s.parse::<Timestamp>().ok());

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ignore or skip order events lacking client_metadata when they are for externally placed orders (they have no Nautilus client order ID)
  2. Ensure all orders submitted to dYdX originate from this adapter so client_metadata is always populated
  3. Check the adapter/exchange SDK versions for schema changes to the order payload
  4. Extend parsing to handle missing client_metadata gracefully if external-order visibility is required

Example fix

// before
let client_metadata: u32 = ws_order.client_metadata.as_ref().ok_or_else(|| anyhow!("Missing required field: client_metadata"))?.parse()?;
// after
let Some(metadata) = ws_order.client_metadata.as_ref() else { return Ok(None) }; // skip external orders
let client_metadata: u32 = metadata.parse().context("Failed to parse client_metadata")?;
Defensive patterns

Strategy: try-catch

Validate before calling

if ws_order.client_metadata.is_none() {
    // external order not placed via this adapter; skip
    return;
}

Type guard

fn has_client_metadata(o: &WsOrder) -> bool {
    o.client_metadata.as_ref().map(|m| m.parse::<u32>().is_ok()).unwrap_or(false)
}

Try / catch

match parse_ws_order_report(...) {
    Err(e) if e.to_string().contains("client_metadata") => {
        debug!("ignoring external order update without client_metadata");
    }
    Err(e) => return Err(e),
    Ok(r) => handle(r),
}

Prevention

When it happens

Trigger: Receiving a WebSocket order update where client_metadata is null/missing — typically orders not placed through this adapter (e.g. placed via dYdX UI or another client) so no Nautilus client metadata was attached.

Common situations: External orders placed outside Nautilus appearing on the websocket stream; exchange or API version changing the payload schema; proto3 optional field omitted by the sender.

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