nautechsystems/nautilus_trader · error · anyhow::Error

Failed to build spread order detail params: {e}

Error message

Failed to build spread order detail params: {e}

What it means

The OKX adapter builds request parameters for a spread order detail lookup via a typed params builder. When `build()` fails (required fields unset or mutually exclusive fields set), the adapter wraps the builder error in this anyhow error. The caller must provide exactly one of client_order_id or venue_order_id.

Source

Thrown at crates/adapters/okx/src/http/client.rs:7056

    ) -> anyhow::Result<Option<OrderStatusReport>> {
        let instrument = self.instrument_from_cache(instrument_id.symbol.inner())?;
        let mut params_builder = GetSpreadOrderParamsBuilder::default();

        match (client_order_id, venue_order_id) {
            (Some(client_order_id), None) => {
                params_builder.cl_ord_id(client_order_id.as_str().to_string());
            }
            (None, Some(venue_order_id)) => {
                params_builder.ord_id(venue_order_id.as_str().to_string());
            }
            _ => anyhow::bail!(
                "Exactly one of client_order_id or venue_order_id is required for a spread order detail request"
            ),
        }

        let params = params_builder
            .build()
            .map_err(|e| anyhow::anyhow!("Failed to build spread order detail params: {e}"))?;
        let orders = match self.inner.get_spread_order(params).await {
            Ok(orders) => orders,
            Err(e) if e.is_order_not_found() => return Ok(None),
            Err(e) => return Err(e.into()),
        };
        let Some(order) = orders.into_iter().next() else {
            return Ok(None);
        };
        let ts_init = self.generate_ts_init();
        let report = parse_spread_order_status_report(
            &order,
            account_id,
            instrument.id(),
            instrument.price_precision(),
            instrument.size_precision(),
            ts_init,
        )?;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure the request supplies exactly one identifier: a non-empty client_order_id OR venue_order_id before calling the detail lookup.
  2. Log/inspect the inner builder error (`{e}`) to see which specific param invariant failed.
  3. If looking up by exchange ID, fetch venue_order_id from a prior order submission/ack rather than leaving it None.

Example fix

// before
let params = SpreadOrderDetailParams::new().build()?; // no id set
// after
let params = SpreadOrderDetailParams::new()
    .client_order_id(client_order_id)
    .build()?;
Defensive patterns

Strategy: validation

Validate before calling

// rust
if client_order_id.is_none() == venue_order_id.is_none() {
    return Err(anyhow!("provide exactly one of client_order_id or venue_order_id"));
}

Prevention

When it happens

Trigger: Calling the spread order detail lookup with neither client_order_id nor venue_order_id set, or failing other builder invariants (e.g. unset required instrument fields), causing `params_builder.build()` to return Err.

Common situations: Reconciliation/retry code that looks up an order status but lost the original client_order_id and never set venue_order_id; code passing empty/None IDs after deserializing partial order records.

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/6736b65dcf8eae8d. Report an issue: GitHub.