{"record":{"id":"d750864ef556939b","repo":"nautechsystems/nautilus_trader","slug":"fill-quantity-overflow-while-aggregating-fill-grou","errorCode":null,"errorMessage":"fill quantity overflow while aggregating fill group","messagePattern":"fill quantity overflow while aggregating fill group","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/live/src/execution/manager.rs","lineNumber":1311,"sourceCode":"                \"order side differs across fill group\"\n            );\n            anyhow::ensure!(\n                fill.venue_position_id == first.venue_position_id,\n                \"venue position ID differs across fill group\"\n            );\n        }\n\n        anyhow::ensure!(\n            first.instrument_id == instrument.id(),\n            \"instrument metadata does not match fill group\"\n        );\n\n        let (quantity, notional) = fills.iter().try_fold(\n            (Decimal::ZERO, Decimal::ZERO),\n            |(quantity, notional), fill| {\n                let fill_quantity = fill.last_qty.as_decimal();\n                let quantity = quantity.checked_add(fill_quantity).ok_or_else(|| {\n                    anyhow::anyhow!(\"fill quantity overflow while aggregating fill group\")\n                })?;\n\n                let fill_notional = fill_quantity\n                    .checked_mul(fill.last_px.as_decimal())\n                    .ok_or_else(|| {\n                        anyhow::anyhow!(\"fill notional overflow while aggregating fill group\")\n                    })?;\n\n                let notional = notional.checked_add(fill_notional).ok_or_else(|| {\n                    anyhow::anyhow!(\"fill notional overflow while aggregating fill group\")\n                })?;\n\n                Ok::<_, anyhow::Error>((quantity, notional))\n            },\n        )?;\n\n        anyhow::ensure!(\n            quantity > Decimal::ZERO,","sourceCodeStart":1293,"sourceCodeEnd":1329,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/live/src/execution/manager.rs#L1293-L1329","documentation":"This error is thrown by the live execution manager when aggregating a group of fills for an order: while summing each fill's `last_qty` as a `Decimal`, a `checked_add` overflowed. NautilusTrader uses checked arithmetic for all discrete quantity/money values and refuses to silently wrap, so the fold aborts with this error instead of producing a wrong aggregate quantity. It indicates fill quantities beyond the Decimal capacity or corrupted fill data.","triggerScenarios":"Calling the fill-group aggregation path (order filled events processed by the live ExecutionManager) with fills whose cumulative `last_qty` exceeds the maximum value representable by the internal fixed-precision Decimal. E.g. extremely large order sizes from a misconfigured instrument, fills with garbage/huge `last_qty` values from a venue adapter bug, or repeated aggregation of fills into an already-large accumulator.","commonSituations":"Exchange adapter returning wrongly scaled quantities (e.g. raw integer size instead of decimal size), an instrument definition whose size_precision mismatch causes giant decimals, historical fill replay with corrupted data, or aggregating thousands of tiny fills in a long-running live session where the running total grows beyond Decimal bounds.","solutions":["Inspect the fills in the group and log each `fill.last_qty` to find the offending oversized or malformed value","Verify the instrument definition (size_precision, size_increment) matches the venue's actual quantity scaling; fix adapter conversion code if quantities are not being scaled correctly","Check for a bug where the same fills are aggregated more than once (double-counting inflates the running sum)","Reduce order/position sizes or split the fill group if genuinely trading quantities near Decimal::MAX","Report the issue with the raw venue fill payloads if values look legitimate — the Decimal bounds should never be reachable in normal trading"],"exampleFix":"// before: adapter sends raw integer size without scaling\nlet qty = Quantity::new(raw_size as f64, 0);\n// after: scale by instrument size precision\nlet qty = Quantity::from_raw(raw_int, instrument.size_precision());","handlingStrategy":"validation","validationCode":"fn fills_aggregate_within_bounds(fills: &[Fill]) -> bool {\n    let mut total = Decimal::ZERO;\n    for f in fills {\n        match total.checked_add(f.last_qty.as_decimal()) {\n            Some(t) => total = t,\n            None => return false,\n        }\n    }\n    true\n}\n","typeGuard":"fn has_valid_fill_quantities(fills: &[Fill]) -> bool {\n    !fills.is_empty()\n        && fills.iter().all(|f| f.last_qty.as_decimal() > Decimal::ZERO)\n}\n","tryCatchPattern":"match manager.aggregate_fill_group(&fills) {\n    Ok(result) => handle(result),\n    Err(e) if e.to_string().contains(\"fill quantity overflow\") => {\n        log::error!(\"oversized/corrupt fill quantities: {e}\");\n        halt_and_reconcile();\n    }\n    Err(e) => return Err(e),\n}\n","preventionTips":["Validate each fill's last_qty is positive and plausible for the instrument before aggregating","Keep instrument size_precision/size_increment definitions in sync with the venue","Deduplicate fill events before aggregation to avoid double-counting","Scale adapter raw values through Quantity::from_raw with the instrument precision"],"tags":["decimal-overflow","arithmetic","execution","fills"],"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-14T00:17:10.932Z"}