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
- 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
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
- 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
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
- Missing required field: order_id
- Unsupported Deribit resolution: {resolution}
- Unknown order direction: {}
- Unknown trade direction: {}
- Derive {label} cannot be represented as f64
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/05f029c4c936ddd3.
Report an issue: GitHub.