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
- Ensure the request supplies exactly one identifier: a non-empty client_order_id OR venue_order_id before calling the detail lookup.
- Log/inspect the inner builder error (`{e}`) to see which specific param invariant failed.
- 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
- Always carry the client_order_id from order submission through to status lookups.
- Never call spread order detail with an empty/None identifier.
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
- Exactly one of client_order_id or venue_order_id is required
- `tick_sz` is empty for {}
- `lot_sz` is empty for {}
- Empty underlying for {inst_id}: instrument may be pre-open o
- Invalid contract type '{}' for {}: expected 'linear' or 'inv
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/6736b65dcf8eae8d.
Report an issue: GitHub.