{"record":{"id":"87c00c54a2e49271","repo":"nautechsystems/nautilus_trader","slug":"order-missing-order-qty-and-cannot-reconstruct-or","errorCode":null,"errorMessage":"Order missing order_qty and cannot reconstruct (order_id={}, cum_qty={:?}, leaves_qty={:?})","messagePattern":"Order missing order_qty and cannot reconstruct \\(order_id=(.+?), cum_qty=(.+?), leaves_qty=(.+?)\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/bitmex/src/http/parse.rs","lineNumber":928,"sourceCode":"            cum,\n            leaves,\n        );\n        let quantity = parse_signed_contracts_quantity(cum + leaves, instrument);\n        let filled_qty = parse_signed_contracts_quantity(cum, instrument);\n        (quantity, filled_qty)\n    } else if order_status == OrderStatus::Canceled || order_status == OrderStatus::Rejected {\n        // For canceled/rejected orders, both quantities will be reconciled from cache\n        // BitMEX sometimes omits all quantity fields in cancel responses\n        log::debug!(\n            \"Order missing quantity fields, using 0 for both (will be reconciled from cache): order_id={:?}, client_order_id={:?}, status={:?}\",\n            order.order_id,\n            order.cl_ord_id,\n            order_status,\n        );\n        let zero_qty = Quantity::zero(instrument.size_precision());\n        (zero_qty, zero_qty)\n    } else {\n        anyhow::bail!(\n            \"Order missing order_qty and cannot reconstruct (order_id={}, cum_qty={:?}, leaves_qty={:?})\",\n            order.order_id,\n            order.cum_qty,\n            order.leaves_qty\n        );\n    };\n    let report_id = UUID4::new();\n    let ts_accepted = order.transact_time.map_or(ts_init, UnixNanos::from);\n    let ts_last = order.timestamp.map_or(ts_init, UnixNanos::from);\n\n    let mut report = OrderStatusReport::new(\n        account_id,\n        instrument_id,\n        None, // client_order_id - will be set later if present\n        venue_order_id,\n        order_side,\n        order_type,\n        time_in_force,","sourceCodeStart":910,"sourceCodeEnd":946,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/bitmex/src/http/parse.rs#L910-L946","documentation":"parse_order_status_report reconstructs order quantities for a BitMEX order status response. When the raw order has no order_qty, it tries to reconstruct order and filled quantities from cum_qty/leaves_qty; if that reconstruction also fails (quantities incompatible with a zero-quantity fallback), it bails with this error. It means the exchange response lacks enough information to build a valid OrderStatusReport.","triggerScenarios":"Calling submit_order, cancel_order, cancel_orders, cancel_all_orders, modify_order, or query_order when BitMEX returns an order status payload with no orderQty field and cum_qty/leaves_qty that cannot yield a valid quantity (e.g. both absent or malformed).","commonSituations":"Querying an order that was rejected before any quantity was recorded; BitMEX API returning partial/amended order data; orders cancelled immediately after submit so the exchange never echoed orderQty; stale or synthetic order rows in reconciliation.","solutions":["Re-query the order via query_order after a short delay so BitMEX returns a complete payload including orderQty","Check the raw BitMEX response (orderQty, cumQty, leavesQty) to confirm which field is missing; if the order was rejected, treat it as rejected rather than reconstructing quantities","Verify the instrument mapping (size_precision) is correct — a wrong instrument can make reconstructed quantities invalid","Upgrade/patch the adapter to fall back to zero quantities for unfillable orders instead of erroring if your workflow tolerates it"],"exampleFix":"// before: caller assumes a report always comes back\nlet report = adapter.query_order(instr, client_order_id).await?;\n// after: treat missing-quantity reconstruction as an unresolvable order state\nmatch adapter.query_order(instr, client_order_id).await {\n    Ok(report) => handle(report),\n    Err(e) if e.to_string().contains(\"cannot reconstruct\") => {\n        log::warn!(\"order {} has no reconstructable qty; polling again\", client_order_id);\n        tokio::time::sleep(Duration::from_millis(250)).await;\n        handle(adapter.query_order(instr, client_order_id).await?)\n    }\n    Err(e) => return Err(e),\n}","handlingStrategy":"validation","validationCode":"fn has_reconstructable_qty(order: &BitmexOrder) -> bool {\n    order.order_qty.is_some()\n        || (order.cum_qty.is_some() && order.leaves_qty.is_some())\n}\n// gate the call: if !has_reconstructable_qty(&raw_order) { poll again or mark order unresolvable }","typeGuard":"fn order_has_qty(order: &BitmexOrder) -> bool {\n    order.order_qty.map(|q| q > 0).unwrap_or(false)\n        || matches!((order.cum_qty, order.leaves_qty), (Some(_), Some(_)))\n}","tryCatchPattern":"match client.query_order(instrument, cl_ord_id).await {\n    Ok(report) => Ok(report),\n    Err(e) if e.to_string().contains(\"cannot reconstruct\") => {\n        warn!(\"no quantity in order status for {cl_ord_id}; retrying\");\n        client.query_order(instrument, cl_ord_id).await\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Poll query_order shortly after submit/cancel so BitMEX has echoed full order data","Log raw BitMEX order payloads to spot missing orderQty fields early","Verify instrument size_precision mappings for every traded symbol","Treat immediately-rejected orders as terminal instead of expecting a full status report"],"tags":["rust","bitmex","order-management","parsing"],"backgroundTag":"unexpected-api-response-shape","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"}