nautechsystems/nautilus_trader · error · anyhow::Error

failed to batch cancel orders

Error message

failed to batch cancel orders

What it means

Polymarket's batch_cancel_orders_command submits a batch of order cancels to the CLOB API. When the batch HTTP call returns Err, each order is marked failed via apply_cancel_http_failure and the task returns "failed to batch cancel orders". The canceled/not_canceled split in the response is the success path; this is the outright call-failure path.

Source

Thrown at crates/adapters/polymarket/src/execution/cancellations.rs:504

            match submitter.cancel_orders(&order_id_refs).await {
                Ok(response) => {
                    for (venue_id_str, order) in &venue_to_order {
                        let vid = VenueOrderId::from(venue_id_str.as_str());
                        process_cancel_result(&response, venue_id_str, order, vid, &emitter, clock);
                    }

                    log::debug!("Batch canceled {} orders", response.canceled.len());
                    Ok(())
                }
                Err(e) => {
                    let orders: Vec<(VenueOrderId, OrderAny)> = venue_to_order
                        .iter()
                        .map(|(venue_id_str, order)| {
                            (VenueOrderId::from(venue_id_str.as_str()), order.clone())
                        })
                        .collect();
                    apply_cancel_http_failure(&e, &orders, &emitter, clock);
                    Err(anyhow::Error::new(e).context("failed to batch cancel orders"))
                }
            }
        });
    }

    fn cancel_venue_order_id(&self, order: &OrderAny) -> Option<VenueOrderId> {
        self.order_contexts
            .venue_order_id(&order.client_order_id())
            .or_else(|| order.venue_order_id())
            .or_else(|| {
                self.core
                    .cache()
                    .venue_order_id(&order.client_order_id())
                    .copied()
            })
    }
}

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the underlying error for the CLOB HTTP status and error payload.
  2. Pre-filter the batch to live, open orders only; drop already-canceled/filled ids.
  3. Verify API credentials and signer nonce are current.
  4. Retry the batch with backoff; on repeated failure, split into smaller batches or per-order cancels.
  5. Confirm batch size is within Polymarket's API limits.

Example fix

// before
let ids: Vec<_> = all_orders.iter().map(|o| o.client_order_id()).collect();
client.batch_cancel_orders(&ids)?;
// after
let ids: Vec<_> = all_orders.iter()
    .filter(|o| o.status() == OrderStatus::Accepted)
    .map(|o| o.client_order_id()).collect();
for chunk in ids.chunks(50) { client.batch_cancel_orders(chunk)?; }
Defensive patterns

Strategy: validation

Validate before calling

// only live orders, within batch limits
let ids: Vec<_> = orders.iter()
    .filter(|o| o.status() == OrderStatus::Accepted)
    .map(|o| o.client_order_id()).collect();
assert!(ids.len() <= MAX_BATCH, "batch too large");

Try / catch

match client.batch_cancel_orders(&ids) {
    Ok(()) => {}
    Err(e) => {
        warn!("batch cancel failed: {e}; splitting batch");
        for half in ids.chunks(ids.len().div_ceil(2).max(1)) {
            retry_with_backoff(|| client.batch_cancel_orders(half));
        }
    }
}

Prevention

When it happens

Trigger: Calling batch_cancel_orders with client_order_ids when the CLOB batch endpoint errors: authentication/nonce failure, malformed batch payload, network error, or venue rejection of the whole request.

Common situations: Batch containing stale or already-terminal order ids; credential desync after restart; exceeding Polymarket batch size limits; transient CLOB outage during volatile markets.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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