{"record":{"id":"141ca57861cb9bd6","repo":"nautechsystems/nautilus_trader","slug":"invalid-order-quantity","errorCode":null,"errorMessage":"invalid order quantity","messagePattern":"invalid order quantity","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/websocket/dispatch.rs","lineNumber":1387,"sourceCode":"    let order_status =\n        crate::execution::parse::resolve_order_status(status.status, order.event_type);\n    let order_side = OrderSide::from(order.side);\n    let time_in_force = TimeInForce::from(order_type);\n    let size_precision = instrument.size_precision();\n    let price_precision = instrument.price_precision();\n    let price_dec = parse_decimal_exact(&order.price)?;\n    anyhow::ensure!(\n        price_dec > Decimal::ZERO && price_dec < Decimal::ONE,\n        \"order price must be in (0, 1)\"\n    );\n    let quantity_dec = parse_decimal_exact(&order.original_size)?;\n    // Unfilled FOK cancellations carry an empty size_matched in captured venue messages\n    let filled_dec = if order.size_matched.is_empty() {\n        Decimal::ZERO\n    } else {\n        parse_decimal_exact(&order.size_matched)?\n    };\n    anyhow::ensure!(\n        quantity_dec > Decimal::ZERO && filled_dec >= Decimal::ZERO,\n        \"invalid order quantity\"\n    );\n    let quantity = Quantity::from_decimal_dp(\n        original_size_to_shares(quantity_dec, price_dec, order.side, order_type)?,\n        size_precision,\n    )?;\n    let filled_qty = Quantity::from_decimal_dp(filled_dec, size_precision)?;\n    let price = Price::from_decimal_dp(price_dec, price_precision)?;\n\n    let mut report = OrderStatusReport::new(\n        account_id,\n        instrument.id(),\n        None,\n        venue_order_id,\n        order_side.into(),\n        OrderType::Limit,\n        time_in_force,","sourceCodeStart":1369,"sourceCodeEnd":1405,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/websocket/dispatch.rs#L1369-L1405","documentation":"build_ws_order_status_report() validates quantities before conversion to shares: the venue-reported original_size must parse to a decimal > 0, and size_matched (filled amount) must be >= 0 (an empty size_matched is treated as 0 for unfilled FOK cancellations). 'invalid order quantity' means original_size was zero/negative or size_matched was negative — the venue message cannot describe a real order, so the report is rejected.","triggerScenarios":"An order-update with original_size \"0\" or empty-but-non-matching values, a negative size_matched from a malformed or schema-changed message, or a fixture/test message missing quantity fields.","commonSituations":"Polymarket API message-shape changes shifting quantity fields; partially-filled cancel messages with unexpected matched sizes; corrupted feed data; hand-written test fixtures with zero sizes.","solutions":["Log the raw order payload to confirm what original_size/size_matched actually contained","Update the adapter's field mapping if the venue schema changed so quantities land in the right fields","Skip non-reportable message shapes upstream instead of building a report with degenerate quantities","Fix test fixtures to carry a positive original_size (and non-negative size_matched)"],"exampleFix":"// before\nanyhow::ensure!(\n    quantity_dec > Decimal::ZERO && filled_dec >= Decimal::ZERO,\n    \"invalid order quantity\"\n);\n// after — reject degenerate messages upstream before parsing\nif order.original_size.is_empty() {\n    return Ok(None); // no original size: nothing to report\n}\nanyhow::ensure!(\n    quantity_dec > Decimal::ZERO && filled_dec >= Decimal::ZERO,\n    \"invalid order quantity\"\n);","handlingStrategy":"validation","validationCode":"let qty: f64 = order.original_size.parse()?;\nlet filled: f64 = if order.size_matched.is_empty() { 0.0 } else { order.size_matched.parse()? };\nif !(qty > 0.0 && filled >= 0.0) {\n    return Ok(None); // degenerate venue message; skip instead of failing the report\n}","typeGuard":"fn has_valid_venue_quantities(order: &WsOrder) -> bool {\n    let qty = order.original_size.parse::<f64>().unwrap_or(0.0);\n    let filled = order.size_matched.parse::<f64>().unwrap_or(0.0);\n    qty > 0.0 && filled >= 0.0\n}","tryCatchPattern":"match build_ws_order_status_report(&instrument, &order, ...) {\n    Ok(report) => emit(report),\n    Err(e) if e.to_string().contains(\"invalid order quantity\") => {\n        log::warn!(\"skipping order update with bad quantities size={:?} matched={:?}: {e:#}\",\n            order.original_size, order.size_matched);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Range-check venue quantities (>0 original, >=0 matched) before consuming updates","Treat empty size_matched as zero only for the documented FOK-cancel case","Watch for venue API schema changes that shift quantity fields","Validate fixtures in tests carry realistic positive sizes"],"tags":["rust","websocket","validation","order-report","polymarket"],"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"}