nautechsystems/nautilus_trader · error
Either client_order_id or venue_order_id must be provided fo
Error message
Either client_order_id or venue_order_id must be provided for each order
What it means
In the batch cancel loop, each per-order entry must carry either the venue order ID or the client order ID. When both Options are None for an entry, the adapter bails because the individual cancel entry cannot be built for Bybit.
Source
Thrown at crates/adapters/bybit/src/http/client.rs:2794
}
let mut cancel_entries = Vec::new();
for ((instrument_id, client_order_id), venue_order_id) in instrument_ids
.iter()
.zip(client_order_ids.iter())
.zip(venue_order_ids.iter())
{
let bybit_symbol = BybitSymbol::new(instrument_id.symbol.as_str())?;
let mut cancel_entry = BybitBatchCancelOrderEntryBuilder::default();
cancel_entry.symbol(bybit_symbol.raw_symbol().to_string());
if let Some(venue_order_id) = venue_order_id {
cancel_entry.order_id(venue_order_id.to_string());
} else if let Some(client_order_id) = client_order_id {
cancel_entry.order_link_id(client_order_id.to_string());
} else {
anyhow::bail!(
"Either client_order_id or venue_order_id must be provided for each order"
);
}
cancel_entries.push(cancel_entry.build().build_anyhow()?);
}
let chunk_limit = batch_endpoint_limit(product_type).min(batch_send_limit(product_type));
for chunk in cancel_entries.chunks(chunk_limit) {
let mut params = BybitBatchCancelOrderParamsBuilder::default();
params.category(product_type);
params.request(chunk.to_vec());
let params = params.build().build_anyhow()?;
let body = serde_json::to_vec(¶ms)?;
let _response: BybitPlaceOrderResponse = self
.innerView on GitHub (pinned to 18893faf8b)
Solutions
- Ensure every batch element has at least one populated identifier
- Filter out orders with no identifier and cancel them via a different path (e.g. cancel-all-orders by symbol)
- Look up the venue order ID from the cache before batching
Example fix
// before
client_ids.push(None); venue_ids.push(None); // unpadded placeholder
// after
if client_id.is_none() && venue_id.is_none() { continue; } // or resolve from cache first Defensive patterns
Strategy: validation
Validate before calling
for (c, v) in client_order_ids.iter().zip(venue_order_ids.iter()) {
anyhow::ensure!(c.is_some() || v.is_some(), "each order needs an identifier");
} Type guard
fn entry_identifiable(c: &Option<ClientOrderId>, v: &Option<VenueOrderId>) -> bool { c.is_some() || v.is_some() } Prevention
- Resolve venue IDs from the cache before batching
- Skip or handle separately orders lacking both IDs
- Keep client_order_ids persisted for all live orders
When it happens
Trigger: Calling batch_cancel_all_orders with one or more positions in the parallel vectors where both client_order_ids[i] and venue_order_ids[i] are None.
Common situations: Batching cancels for orders whose venue acknowledgement never arrived and whose client ID was not stored; placeholder None entries used to pad the vectors to equal length.
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
- Batch cancel limit is {endpoint_limit} orders for {product_t
- Either client_order_id or venue_order_id must be provided
- instrument_ids, client_order_ids, and venue_order_ids must h
- Batch cancel limit is {call_limit} orders for {}
- Unspecified Bybit order side
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/ba34a96da076ff19.
Report an issue: GitHub.