{"record":{"id":"35f5de3e52c808d0","repo":"nautechsystems/nautilus_trader","slug":"missing-required-field-order-id","errorCode":null,"errorMessage":"Missing required field: order_id","messagePattern":"Missing required field: order_id","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/dydx/src/websocket/parse.rs","lineNumber":358,"sourceCode":"    let created_at_height: u64 = ws_fill\n        .created_at_height\n        .as_ref()\n        .map(|s| s.parse())\n        .transpose()\n        .context(\"Failed to parse created_at_height\")?\n        .unwrap_or(0);\n\n    let client_metadata: u32 = ws_fill\n        .client_metadata\n        .as_ref()\n        .ok_or_else(|| anyhow::anyhow!(\"Missing required field: client_metadata\"))?\n        .parse()\n        .context(\"Failed to parse client_metadata\")?;\n\n    let order_id = ws_fill\n        .order_id\n        .clone()\n        .ok_or_else(|| anyhow::anyhow!(\"Missing required field: order_id\"))?;\n\n    let created_at = ws_fill\n        .created_at\n        .parse::<Timestamp>()\n        .context(\"Failed to parse created_at\")?;\n\n    Ok(Fill {\n        id: ws_fill.id.clone(),\n        side: ws_fill.side,\n        liquidity: ws_fill.liquidity,\n        fill_type: ws_fill.fill_type,\n        market: ws_fill.market,\n        market_type: ws_fill.market_type.unwrap_or(DydxTickerType::Perpetual),\n        price,\n        size,\n        fee,\n        created_at,\n        created_at_height,","sourceCodeStart":340,"sourceCodeEnd":376,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/dydx/src/websocket/parse.rs#L340-L376","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the raw WS payload to confirm the exchange really omitted order_id","Upgrade the adapter/exchange SDK to a version matching the current dYdX proto schema","Skip fills without order_id if they are special fill types irrelevant to order tracking","Report the malformed payload to the exchange/adapter maintainers if it persists"],"exampleFix":"// before\nlet order_id = ws_fill.order_id.clone().ok_or_else(|| anyhow!(\"Missing required field: order_id\"))?;\n// after\nlet Some(order_id) = ws_fill.order_id.clone() else { tracing::warn!(\"fill missing order_id, skipping\"); return Ok(None) };","handlingStrategy":"validation","validationCode":"if ws_fill.order_id.is_none() {\n    eprintln!(\"fill missing order_id; cannot attribute to an order\");\n    return;\n}","typeGuard":"fn has_order_id(f: &WsFill) -> bool {\n    f.order_id.as_deref().map(|s| !s.is_empty()).unwrap_or(false)\n}","tryCatchPattern":"match parse_ws_fill_report(...) {\n    Err(e) if e.to_string().contains(\"order_id\") => {\n        warn!(\"dropping fill with missing order_id\");\n    }\n    Err(e) => return Err(e),\n    Ok(r) => handle(r),\n}","preventionTips":["Validate fill payloads for required fields when onboarding new dYdX fill types (e.g. liquidations)","Keep the adapter and exchange SDK versions in sync","Report persistent malformed payloads to the exchange"],"tags":["rust","dydx","websocket","parsing"],"backgroundTag":"missing-required-argument","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}