nautechsystems/nautilus_trader · error

Overflow occurred when adding `Quantity`

Error message

Overflow occurred when adding `Quantity`

What it means

Quantity implements Add via checked_add on raw fixed-point values; a None result (sum above QUANTITY_RAW_MAX) makes the expect panic. Silent wrapping of a quantity would corrupt order/position accounting, so the library aborts loudly instead.

Source

Thrown at crates/model/src/types/quantity.rs:702

    type Target = QuantityRaw;

    fn deref(&self) -> &Self::Target {
        &self.raw
    }
}

impl Add for Quantity {
    type Output = Self;
    fn add(self, rhs: Self) -> Self::Output {
        assert!(
            raw_scales_match(self.precision, rhs.precision),
            "Cannot add `Quantity` values with mismatched decimal scales"
        );
        Self {
            raw: self
                .raw
                .checked_add(rhs.raw)
                .expect("Overflow occurred when adding `Quantity`"),
            precision: self.precision.max(rhs.precision),
        }
    }
}

impl Sum for Quantity {
    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
        iter.reduce(|acc, x| acc + x)
            .unwrap_or_else(|| Self::zero(0))
    }
}

impl<'a> Sum<&'a Self> for Quantity {
    fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
        iter.copied().sum()
    }
}

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Accumulate in Decimal or u128 and construct/validate a Quantity at the end instead of repeatedly adding Quantity.
  2. Check remaining headroom (QUANTITY_RAW_MAX - lhs.raw) >= rhs.raw before adding.
  3. Enforce domain caps (max order size, max position) so accumulated raw values stay far below the bound.
  4. Verify both quantities use consistent units/precision from each venue before summing.

Example fix

// before
let filled: Quantity = fills.iter().map(|f| f.qty).sum(); // panics on very large totals
// after
let total = fills.iter().fold(Decimal::ZERO, |a, f| a + f.qty.as_decimal());
let filled = Quantity::new(total, precision); // validates range
Defensive patterns

Strategy: fallback

Validate before calling

// Rust
fn checked_quantity_add(a: Quantity, b: Quantity) -> Option<Quantity> {
    (a.precision == b.precision)
        .then(|| a.raw.checked_add(b.raw))
        .flatten()
        .map(|raw| Quantity { raw, precision: a.precision })
}

Try / catch

// Accumulate in Decimal, then build once:
let total = fills.iter().fold(Decimal::ZERO, |a, f| a + f.qty.as_decimal());
assert!(total <= MAX_QUANTITY_DECIMAL);
let filled = Quantity::new(total, precision);

Prevention

When it happens

Trigger: Using + on two Quantity values with matching precision whose raw sum exceeds QUANTITY_RAW_MAX; also via impl Sum / fold over collections of large quantities.

Common situations: Accumulating filled quantities across many fills; summing position sizes in a portfolio loop; unit mismatches where one venue reports in minimal units and inflates sums.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/395d4614ed59e66d. Report an issue: GitHub.