nautechsystems/nautilus_trader · error

Raw value exceeds MoneyRaw range in Money::from_mantissa_exp

Error message

Raw value exceeds MoneyRaw range in Money::from_mantissa_exponent

What it means

After computing the fixed-point i128 raw value, Money::from_mantissa_exponent converts it into MoneyRaw via try_into and panics with this message if the value falls outside the MoneyRaw range. The following assert re-checks MONEY_RAW_MIN/MAX bounds. This is a secondary range guard distinct from the i128 arithmetic overflow check.

Source

Thrown at crates/model/src/types/money.rs:289

    #[must_use]
    pub fn from_mantissa_exponent(mantissa: i64, exponent: i8, currency: Currency) -> Self {
        check_fixed_precision(currency.precision).expect_display(FAILED);

        if mantissa == 0 {
            return Self { raw: 0, currency };
        }

        let raw_i128 =
            mantissa_exponent_to_fixed_i128(i128::from(mantissa), exponent, currency.precision)
                .expect("Overflow in Money::from_mantissa_exponent");

        #[allow(
            clippy::useless_conversion,
            reason = "i128 to MoneyRaw is real when not high-precision"
        )]
        let raw: MoneyRaw = raw_i128
            .try_into()
            .expect("Raw value exceeds MoneyRaw range in Money::from_mantissa_exponent");
        assert!(
            raw >= MONEY_RAW_MIN && raw <= MONEY_RAW_MAX,
            "`raw` value {raw} exceeded bounds [{MONEY_RAW_MIN}, {MONEY_RAW_MAX}] for Money"
        );

        Self { raw, currency }
    }

    /// Creates a new [`Money`] instance with a value of zero with the given [`Currency`].
    ///
    /// # Panics
    ///
    /// Panics if `currency.precision` exceeds the maximum allowed by `check_fixed_precision`.
    #[must_use]
    pub fn zero(currency: Currency) -> Self {
        check_fixed_precision(currency.precision).expect_display(FAILED);
        Self { raw: 0, currency }
    }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the amount against MONEY_RAW_MAX/MIN (or the currency's max Money) before constructing.
  2. Compile with the high-precision feature so MoneyRaw is i128 and cannot hit this narrowing failure.
  3. Split or rescale the amount (different currency units) to fit the representable range.

Example fix

// before
let m = Money::from_mantissa_exponent(mantissa, exponent, currency); // panics if raw > MONEY_RAW_MAX
// after
if mantissa.abs() > (MONEY_RAW_MAX as i128 / scale_for(exponent, currency.precision)) {
    return Err(...);
}
let m = Money::from_mantissa_exponent(mantissa, exponent, currency);
Defensive patterns

Strategy: validation

Validate before calling

if amount_abs > MONEY_RAW_MAX_scaled_for(currency) {
    return Err("amount exceeds MoneyRaw range for currency precision");
}
let m = Money::from_mantissa_exponent(mantissa, exponent, currency);

Type guard

fn in_money_range(raw_i128: i128) -> bool {
    raw_i128 >= MONEY_RAW_MIN as i128 && raw_i128 <= MONEY_RAW_MAX as i128
}

Prevention

When it happens

Trigger: Money::from_mantissa_exponent with a mantissa/exponent pair whose i128 result is valid but exceeds MONEY_RAW_MAX (relevant in non-high-precision builds where MoneyRaw is narrower than i128).

Common situations: Non-high-precision builds handling amounts beyond the narrower raw type's range; loading historical or synthetic datasets with extreme amounts; currency configured with wrong precision amplifying the magnitude.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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