nautechsystems/nautilus_trader · error
Overflow occurred when adding `Money`
Error message
Overflow occurred when adding `Money`
What it means
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.
Source
Thrown at crates/model/src/types/money.rs:599
}
impl Add for Money {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
assert_eq!(
self.currency, rhs.currency,
"Currency mismatch: cannot add {} to {}",
rhs.currency.code, self.currency.code
);
assert!(
raw_scales_match(self.currency.precision, rhs.currency.precision),
"Cannot add `Money` values with mismatched decimal scales"
);
Self {
raw: self
.raw
.checked_add(rhs.raw)
.expect("Overflow occurred when adding `Money`"),
currency: self.currency,
}
}
}
impl Sub for Money {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
assert_eq!(
self.currency, rhs.currency,
"Currency mismatch: cannot subtract {} from {}",
rhs.currency.code, self.currency.code
);
assert!(
raw_scales_match(self.currency.precision, rhs.currency.precision),
"Cannot subtract `Money` values with mismatched decimal scales"
);
Self {View on GitHub (pinned to 18893faf8b)
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.
Example fix
// before let total = orders.iter().fold(Money::zero(USD), |acc, o| acc + o.notional()); // may panic // after let total_dec = orders.iter().fold(Decimal::ZERO, |acc, o| acc + o.notional().as_decimal()); let total = Money::new(total_dec, USD); // validate range once
Defensive patterns
Strategy: try-catch
Validate before calling
if a.raw.checked_add(b.raw).is_none() {
return Err(overflow_err());
}
let sum = a + b; Type guard
fn add_will_overflow(a: Money, b: Money) -> bool {
a.raw.checked_add(b.raw).is_none()
} Try / catch
// Money addition panics rather than returning Result; pre-check instead
if a.raw.checked_add(b.raw).is_none() {
// handle overflow (cap, log, escalate)
} else {
let sum = a + b;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Accumulating PnL, balances, or notional totals over many trades until the running total exceeds the raw range; account aggregation jobs over large portfolios.
Related errors
- WETH balance overflow for included transaction {tx_hash} at
- initial margin calculation overflow
- maintenance margin calculation overflow
- Decimal overflow adding {lhs} and {rhs}
- Decimal overflow subtracting {rhs} from {lhs}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/26447e4e067b5edb.
Report an issue: GitHub.