nautechsystems/nautilus_trader · error · anyhow::Error

venue_order_ids cannot be empty

Error message

venue_order_ids cannot be empty

What it means

This error is raised by the BitMEX HTTP adapter's cancel_orders method when the caller passes Some(venue_order_ids) but the collection is empty. BitMEX's cancel order endpoint requires at least one order identifier, and an empty 'orderID' list would produce a malformed request. The bail stops the request before it is sent to the venue.

Source

Thrown at crates/adapters/bitmex/src/http/client.rs:1851

    /// Returns an error if:
    /// - Credentials are missing.
    /// - The request fails.
    /// - The order doesn't exist.
    /// - The API returns an error.
    pub async fn cancel_orders(
        &self,
        instrument_id: InstrumentId,
        client_order_ids: Option<Vec<ClientOrderId>>,
        venue_order_ids: Option<Vec<VenueOrderId>>,
    ) -> anyhow::Result<Vec<OrderStatusReport>> {
        let mut params = super::query::DeleteOrderParamsBuilder::default();
        params.text(NAUTILUS_TRADER);

        // BitMEX API requires either client order IDs or venue order IDs, not both
        // Prioritize venue order IDs if both are provided
        if let Some(venue_order_ids) = venue_order_ids {
            if venue_order_ids.is_empty() {
                anyhow::bail!("venue_order_ids cannot be empty");
            }
            params.order_id(
                venue_order_ids
                    .iter()
                    .map(|id| id.to_string())
                    .collect::<Vec<_>>(),
            );
        } else if let Some(client_order_ids) = client_order_ids {
            if client_order_ids.is_empty() {
                anyhow::bail!("client_order_ids cannot be empty");
            }
            params.cl_ord_id(
                client_order_ids
                    .iter()
                    .map(|id| id.to_string())
                    .collect::<Vec<_>>(),
            );
        } else {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Only wrap the venue order ID collection in Some when it contains at least one ID
  2. Check venue_order_ids.is_empty() at the call site before invoking cancel_orders
  3. If no venue order IDs exist, pass None and use client_order_ids instead, or skip the cancel call entirely

Example fix

// before
let ids: Vec<VenueOrderId> = working.iter().map(|o| o.venue_order_id.clone()).collect();
client.cancel_orders(None, Some(ids)).await?;
// after
let ids: Vec<VenueOrderId> = working.iter().map(|o| o.venue_order_id.clone()).collect();
if ids.is_empty() { return Ok(()); }
client.cancel_orders(None, Some(ids)).await?;
Defensive patterns

Strategy: validation

Validate before calling

if let Some(ids) = &venue_order_ids {
    if ids.is_empty() { return Err(anyhow!("venue_order_ids must not be empty")); }
}
client.cancel_orders(client_order_ids, venue_order_ids).await?;

Type guard

fn has_ids(ids: &Option<Vec<VenueOrderId>>) -> bool {
    ids.as_ref().is_some_and(|v| !v.is_empty())
}

Try / catch

match client.cancel_orders(client_order_ids, venue_order_ids).await {
    Ok(reports) => { /* handle */ }
    Err(e) if e.to_string().contains("cannot be empty") => { /* fix inputs and retry */ }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling cancel_orders with venue_order_ids=Some(vec![]) — i.e. the Option is set but the Vec contains no IDs. Typically happens when caller code filters or collects order IDs from an empty set of working orders but still wraps the result in Some.

Common situations: Batch-cancel flows where order IDs were gathered from a cached or queried order list that turned out to be empty; code that distinguishes 'not provided' from 'empty list' incorrectly.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/510ce8ece4ada81e. Report an issue: GitHub.