{"record":{"id":"2a2944e2b5d6cd05","repo":"nautechsystems/nautilus_trader","slug":"batch-cancel-limit-is-call-limit-orders-for","errorCode":null,"errorMessage":"Batch cancel limit is {call_limit} orders for {}","messagePattern":"Batch cancel limit is (.+?) orders for (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/bybit/src/http/client.rs","lineNumber":2772,"sourceCode":"        instrument_ids: Vec<InstrumentId>,\n        client_order_ids: Vec<Option<ClientOrderId>>,\n        venue_order_ids: Vec<Option<VenueOrderId>>,\n    ) -> anyhow::Result<Vec<OrderStatusReport>> {\n        if instrument_ids.len() != client_order_ids.len()\n            || instrument_ids.len() != venue_order_ids.len()\n        {\n            anyhow::bail!(\n                \"instrument_ids, client_order_ids, and venue_order_ids must have the same length\"\n            );\n        }\n\n        if instrument_ids.is_empty() {\n            return Ok(Vec::new());\n        }\n\n        let call_limit = batch_call_limit(product_type);\n        if instrument_ids.len() > call_limit {\n            anyhow::bail!(\n                \"Batch cancel limit is {call_limit} orders for {}\",\n                product_type.as_str()\n            );\n        }\n\n        let mut cancel_entries = Vec::new();\n\n        for ((instrument_id, client_order_id), venue_order_id) in instrument_ids\n            .iter()\n            .zip(client_order_ids.iter())\n            .zip(venue_order_ids.iter())\n        {\n            let bybit_symbol = BybitSymbol::new(instrument_id.symbol.as_str())?;\n            let mut cancel_entry = BybitBatchCancelOrderEntryBuilder::default();\n            cancel_entry.symbol(bybit_symbol.raw_symbol().to_string());\n\n            if let Some(venue_order_id) = venue_order_id {\n                cancel_entry.order_id(venue_order_id.to_string());","sourceCodeStart":2754,"sourceCodeEnd":2790,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/bybit/src/http/client.rs#L2754-L2790","documentation":"Bybit caps the number of orders per batch cancel request depending on product type (batch call limit). The adapter enforces this limit client-side and bails if the batch exceeds it, to avoid the venue rejecting the whole request.","triggerScenarios":"Calling batch_cancel_all_orders with more orders in the batch than batch_call_limit(product_type) allows for that product type.","commonSituations":"Cancelling a large open-order book in one call during risk-off flows; linear product types with larger limits used where the spot limit applies (or vice versa).","solutions":["Split the batch into chunks of at most the product-type call limit and issue multiple requests","Check instrument_ids.len() against the limit before calling and chunk accordingly","Handle cancellation in smaller routine batches instead of one bulk call"],"exampleFix":"// before\nclient.batch_cancel_all_orders(product_type, symbol, ids, cids, vids).await?;\n// after\nfor chunk in ids.chunks(call_limit) { /* chunk all parallel vectors */ ... }","handlingStrategy":"validation","validationCode":"let call_limit = bybit_batch_call_limit(product_type);\nanyhow::ensure!(instrument_ids.len() <= call_limit, \"batch of {} exceeds limit {}\", instrument_ids.len(), call_limit);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Chunk batch cancels by product-type limit","Prefer streaming cancels over very large bulk calls","Consult batch_call_limit per product type before sizing batches"],"tags":["bybit","batch-cancel","rate-limit"],"backgroundTag":"value-out-of-range","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}