{"record":{"id":"a00b13ff6754ca15","repo":"nautechsystems/nautilus_trader","slug":"fill-notional-overflow-while-aggregating-fill-grou","errorCode":null,"errorMessage":"fill notional overflow while aggregating fill group","messagePattern":"fill notional overflow while aggregating fill group","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/live/src/execution/manager.rs","lineNumber":1317,"sourceCode":"        }\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,\n            \"fill group quantity is not positive\"\n        );\n\n        let order_qty = Quantity::from_decimal_dp(quantity, instrument.size_precision())?;\n        let avg_px = notional\n            .checked_div(quantity)","sourceCodeStart":1299,"sourceCodeEnd":1335,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/live/src/execution/manager.rs#L1299-L1335","documentation":"This error is thrown when computing a single fill's notional value during fill-group aggregation: `fill.last_qty.as_decimal().checked_mul(fill.last_px.as_decimal())` overflowed. The library uses checked Decimal arithmetic for money values and aborts rather than produce a wrapped (wrong) notional. It means a fill's quantity times price exceeds Decimal capacity or one of the values is corrupt.","triggerScenarios":"Processing a fill whose `last_qty * last_px` product exceeds the internal Decimal maximum — e.g. a huge quantity combined with a high price, a fill with a corrupted/malformed `last_px` or `last_qty` from the venue adapter, or wrongly scaled values (price in raw ticks, quantity unscaled).","commonSituations":"Exchange adapter reporting price or quantity in raw integer representation without applying precision scaling; instrument definition with wrong price precision causing absurd decimal magnitudes; corrupted historical fill data replayed during live reconciliation; extremely high-priced instruments with large fill sizes near arithmetic bounds.","solutions":["Log and inspect the offending fill's `last_qty` and `last_px` to identify which value is abnormally large","Verify the adapter converts venue price/quantity into the instrument's defined precision correctly (not raw ticks or raw size)","Check the instrument definition's price_precision/size_precision matches the venue","If data is genuinely huge, split the aggregation or report upstream — Decimal bounds should not be hit by realistic fills"],"exampleFix":"// before: price from raw ticks, unscaled\nlet px = Price::from_raw(raw_tick, 0);\n// after: apply instrument price precision\nlet px = Price::from_raw(raw_tick, instrument.price_precision());","handlingStrategy":"validation","validationCode":"fn fill_notional_representable(fill: &Fill) -> bool {\n    fill.last_qty\n        .as_decimal()\n        .checked_mul(fill.last_px.as_decimal())\n        .map(|n| n < Decimal::from(10u64.pow(30)))\n        .unwrap_or(false)\n}\n","typeGuard":"fn has_plausible_fill(f: &Fill, max_notional: Decimal) -> bool {\n    f.last_qty.as_decimal() > Decimal::ZERO\n        && f.last_px.as_decimal() > Decimal::ZERO\n        && f.last_qty.as_decimal().checked_mul(f.last_px.as_decimal())\n            .map(|n| n <= max_notional)\n            .unwrap_or(false)\n}\n","tryCatchPattern":"match manager.aggregate_fill_group(&fills) {\n    Ok(r) => handle(r),\n    Err(e) if e.to_string().contains(\"fill notional overflow\") => {\n        log::error!(\"fill notional overflow: {e}\");\n        quarantine_fills(&fills);\n    }\n    Err(e) => return Err(e),\n}\n","preventionTips":["Sanity-check each fill's price against the instrument's recent price range before use","Ensure the adapter converts raw venue prices with the instrument's price_precision","Reject fills whose implied notional exceeds a configured sane maximum","Log raw venue fill payloads to enable post-mortem diagnosis of malformed values"],"tags":["decimal-overflow","arithmetic","execution","notional"],"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"}