nautechsystems/nautilus_trader · critical
Overflow in Price::from_mantissa_exponent
Error message
Overflow in Price::from_mantissa_exponent
What it means
Price::from_mantissa_exponent builds a fixed-point Price by converting a mantissa+exponent into a fixed i128 raw value via mantissa_exponent_to_fixed_i128; when the scaled value cannot be represented in i128 at the requested precision, that helper returns None and this expect panics. The library throws it because Price stores a bounded fixed-point raw integer and silently wrapping would corrupt prices.
Source
Thrown at crates/model/src/types/price.rs:525
/// Creates a new [`Price`] from a mantissa/exponent pair using pure integer arithmetic.
///
/// The value is `mantissa * 10^exponent`. This avoids all floating-point and Decimal
/// operations, making it ideal for exchange data that arrives as mantissa/exponent pairs.
///
/// # Panics
///
/// Panics if the resulting raw value exceeds [`PRICE_RAW_MAX`] or [`PRICE_RAW_MIN`].
#[must_use]
pub fn from_mantissa_exponent(mantissa: i64, exponent: i8, precision: u8) -> Self {
check_fixed_precision(precision).expect_display(FAILED);
if mantissa == 0 {
return Self { raw: 0, precision };
}
let raw_i128 = mantissa_exponent_to_fixed_i128(i128::from(mantissa), exponent, precision)
.expect("Overflow in Price::from_mantissa_exponent");
#[allow(
clippy::useless_conversion,
reason = "i128 to PriceRaw is real when not high-precision"
)]
let raw: PriceRaw = raw_i128
.try_into()
.expect("Raw value exceeds PriceRaw range in Price::from_mantissa_exponent");
assert!(
raw >= PRICE_RAW_MIN && raw <= PRICE_RAW_MAX,
"`raw` value {raw} exceeded bounds [{PRICE_RAW_MIN}, {PRICE_RAW_MAX}] for Price"
);
Self { raw, precision }
}
/// Checked variant of [`Price::from_mantissa_exponent`].
///View on GitHub (pinned to 18893faf8b)
Solutions
- Reduce the mantissa magnitude or use an exponent consistent with the instrument's precision so the scaled value fits in i128.
- Pre-check the magnitude: compute the intended decimal value and confirm |value| * 10^precision < 2^127 before calling.
- Clamp or reject the input price at the data-ingestion boundary (validate against instrument price precision and max price).
- If you need larger ranges, perform the computation in a big-integer/Decimal type first and only construct Price once it fits.
Example fix
// before let price = Price::from_mantissa_exponent(9999999999_i64, 30, 9); // panics: scaled value overflows i128 // after let price = Price::from_mantissa_exponent(1234567_i64, -4, 9); // 123.4567 at precision 9, fits i128
Defensive patterns
Strategy: validation
Validate before calling
// Rust
fn can_build_price(mantissa: i64, exponent: i8, precision: u8) -> bool {
// |mantissa| * 10^(exponent - precision) must fit i128
let diff = i32::from(exponent) - i32::from(precision);
const I128_MAX_LOG10: i32 = 38;
mantissa.abs() <= i64::MAX / 2
&& (mantissa.checked_ilog10().map(|d| d as i32).unwrap_or(0) + diff) <= I128_MAX_LOG10
} Type guard
fn fits_i128(value: Decimal, precision: u8) -> bool {
let scaled = value * Decimal::from(10_u32.pow(u32::from(precision)));
scaled.abs() <= Decimal::from(i128::MAX)
} Prevention
- Validate instrument tick-size/precision config at load time and reject absurd exponents.
- Convert external price strings through Decimal and range-check before constructing Price.
- Keep exponents aligned with the instrument's declared precision.
- Add unit tests for boundary prices at max precision.
When it happens
Trigger: Calling Price::from_mantissa_exponent(mantissa, exponent, precision) where mantissa scaled by 10^(exponent - precision) or 10^(precision - exponent) exceeds i128 range, e.g. a very large mantissa combined with a large positive exponent, or a huge precision gap requiring a massive 10^n multiplier.
Common situations: Parsing exchange instrument definitions with absurd tick-size exponents; ingesting bad venue config where precision is set far larger than the mantissa supports; hand-constructing prices from strings with wrong exponent conventions.
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
- Raw value exceeds PriceRaw range in Price::from_mantissa_exp
- Overflow occurred when adding `Price`
- Liquidity addition overflow: x={current}, y={y}, delta={delt
- precision exceeded i8 range
- mul_div overflow
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/fd65b646f274795e.
Report an issue: GitHub.