{"record":{"id":"05f029c4c936ddd3","repo":"nautechsystems/nautilus_trader","slug":"missing-required-field-client-metadata","errorCode":null,"errorMessage":"Missing required field: client_metadata","messagePattern":"Missing required field: client_metadata","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/dydx/src/websocket/parse.rs","lineNumber":197,"sourceCode":"        .unwrap_or(Decimal::ZERO);\n\n    // Saturate to zero if total_filled exceeds size (edge case: rounding or partial fills)\n    let remaining_size = (size - total_filled).max(Decimal::ZERO);\n\n    let price: Decimal = ws_order.price.parse().context(\"Failed to parse price\")?;\n\n    let created_at_height: u64 = ws_order\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_order\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_flags: u32 = ws_order\n        .order_flags\n        .parse()\n        .context(\"Failed to parse order_flags\")?;\n\n    let good_til_block = ws_order\n        .good_til_block\n        .as_ref()\n        .and_then(|s| s.parse::<u64>().ok());\n\n    let good_til_block_time = ws_order\n        .good_til_block_time\n        .as_ref()\n        .and_then(|s| s.parse::<Timestamp>().ok());\n","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/dydx/src/websocket/parse.rs#L179-L215","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Ignore or skip order events lacking client_metadata when they are for externally placed orders (they have no Nautilus client order ID)","Ensure all orders submitted to dYdX originate from this adapter so client_metadata is always populated","Check the adapter/exchange SDK versions for schema changes to the order payload","Extend parsing to handle missing client_metadata gracefully if external-order visibility is required"],"exampleFix":"// before\nlet client_metadata: u32 = ws_order.client_metadata.as_ref().ok_or_else(|| anyhow!(\"Missing required field: client_metadata\"))?.parse()?;\n// after\nlet Some(metadata) = ws_order.client_metadata.as_ref() else { return Ok(None) }; // skip external orders\nlet client_metadata: u32 = metadata.parse().context(\"Failed to parse client_metadata\")?;","handlingStrategy":"try-catch","validationCode":"if ws_order.client_metadata.is_none() {\n    // external order not placed via this adapter; skip\n    return;\n}","typeGuard":"fn has_client_metadata(o: &WsOrder) -> bool {\n    o.client_metadata.as_ref().map(|m| m.parse::<u32>().is_ok()).unwrap_or(false)\n}","tryCatchPattern":"match parse_ws_order_report(...) {\n    Err(e) if e.to_string().contains(\"client_metadata\") => {\n        debug!(\"ignoring external order update without client_metadata\");\n    }\n    Err(e) => return Err(e),\n    Ok(r) => handle(r),\n}","preventionTips":["Place all orders through the adapter so client_metadata is always attached","Filter or tag externally placed orders as expected to lack metadata","Watch for schema changes in dYdX proto payloads after SDK upgrades"],"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-14T00:17:10.932Z"}