{"record":{"id":"26447e4e067b5edb","repo":"nautechsystems/nautilus_trader","slug":"overflow-occurred-when-adding-money","errorCode":null,"errorMessage":"Overflow occurred when adding `Money`","messagePattern":"Overflow occurred when adding `Money`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/types/money.rs","lineNumber":599,"sourceCode":"}\n\nimpl Add for Money {\n    type Output = Self;\n    fn add(self, rhs: Self) -> Self::Output {\n        assert_eq!(\n            self.currency, rhs.currency,\n            \"Currency mismatch: cannot add {} to {}\",\n            rhs.currency.code, self.currency.code\n        );\n        assert!(\n            raw_scales_match(self.currency.precision, rhs.currency.precision),\n            \"Cannot add `Money` values with mismatched decimal scales\"\n        );\n        Self {\n            raw: self\n                .raw\n                .checked_add(rhs.raw)\n                .expect(\"Overflow occurred when adding `Money`\"),\n            currency: self.currency,\n        }\n    }\n}\n\nimpl Sub for Money {\n    type Output = Self;\n    fn sub(self, rhs: Self) -> Self::Output {\n        assert_eq!(\n            self.currency, rhs.currency,\n            \"Currency mismatch: cannot subtract {} from {}\",\n            rhs.currency.code, self.currency.code\n        );\n        assert!(\n            raw_scales_match(self.currency.precision, rhs.currency.precision),\n            \"Cannot subtract `Money` values with mismatched decimal scales\"\n        );\n        Self {","sourceCodeStart":581,"sourceCodeEnd":617,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/types/money.rs#L581-L617","documentation":"The Add impl for Money adds the two raw fixed-point values with checked_add and panics with this message on overflow. Both operands must share currency precision; overflow means the sum exceeds the MoneyRaw representable range. The library treats arithmetic overflow as a bug-level panic rather than a silent wrap.","triggerScenarios":"money_a + money_b where the raw sum exceeds MONEY_RAW_MAX, e.g. adding two near-maximum amounts of the same currency with matching precision.","commonSituations":"Accumulating PnL, balances, or notional totals over many trades until the running total exceeds the raw range; account aggregation jobs over large portfolios.","solutions":["Check that the running total stays within MONEY range before each addition (compare against MONEY_RAW_MAX-scaled value).","Aggregate in a wider type (i128/Decimal) and convert to Money only at the end.","Compile with high-precision so MoneyRaw is i128, giving far more headroom."],"exampleFix":"// before\nlet total = orders.iter().fold(Money::zero(USD), |acc, o| acc + o.notional()); // may panic\n// after\nlet total_dec = orders.iter().fold(Decimal::ZERO, |acc, o| acc + o.notional().as_decimal());\nlet total = Money::new(total_dec, USD); // validate range once","handlingStrategy":"try-catch","validationCode":"if a.raw.checked_add(b.raw).is_none() {\n    return Err(overflow_err());\n}\nlet sum = a + b;","typeGuard":"fn add_will_overflow(a: Money, b: Money) -> bool {\n    a.raw.checked_add(b.raw).is_none()\n}","tryCatchPattern":"// Money addition panics rather than returning Result; pre-check instead\nif a.raw.checked_add(b.raw).is_none() {\n    // handle overflow (cap, log, escalate)\n} else {\n    let sum = a + b;\n}","preventionTips":["Accumulate long series in i128/Decimal and convert to Money at the end.","Enforce domain-level caps on balance/notional totals.","Enable high-precision builds for large ledgers."],"tags":["rust","overflow","money","arithmetic"],"backgroundTag":"integer-overflow","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"}