nautechsystems/nautilus_trader · error
Fixed-point scale fits QuantityRaw
Error message
Fixed-point scale fits QuantityRaw
What it means
Quantity::mul multiplies two fixed-point quantities using checked_mul_div with a scale scalar. Before scaling, the code converts raw_scale(min precision) into a QuantityRaw (u64-backed); this panic fires when that scaled value cannot fit in QuantityRaw. It is an internal invariant: for precisions <= FIXED_PRECISION the scale should always fit, so hitting this indicates an unexpectedly large precision.
Source
Thrown at crates/model/src/types/quantity.rs:749
.checked_sub(rhs.raw)
.expect("Underflow occurred when subtracting `Quantity`"),
precision: self.precision.max(rhs.precision),
}
}
}
impl Mul for Quantity {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
let result_raw = if self.raw != QUANTITY_UNDEF
&& rhs.raw != QUANTITY_UNDEF
&& self.precision <= FIXED_PRECISION
&& rhs.precision <= FIXED_PRECISION
{
checked_mul_div_fixed(self.raw, rhs.raw)
} else {
let scalar = QuantityRaw::try_from(raw_scale(self.precision.min(rhs.precision)))
.expect("Fixed-point scale fits QuantityRaw");
checked_mul_div_raw(self.raw, rhs.raw, scalar)
}
.filter(|raw| *raw <= QUANTITY_RAW_MAX)
.expect("Overflow occurred when multiplying `Quantity`");
Self {
raw: result_raw,
precision: self.precision.max(rhs.precision),
}
}
}
impl Add<Decimal> for Quantity {
type Output = Decimal;
fn add(self, rhs: Decimal) -> Self::Output {
self.as_decimal() + rhs
}
}View on GitHub (pinned to 18893faf8b)
Solutions
- Check the precision of both operands; cap them at FIXED_PRECISION before multiplying.
- Verify instrument definitions (price/size precision) are correct and within supported limits.
- If precision must exceed FIXED_PRECISION, use checked arithmetic or higher-width intermediates instead of relying on Quantity::mul.
- Report as a bug if it fires with precision <= FIXED_PRECISION; the invariant should hold.
Example fix
// before let c = qty_a * qty_b; // panics if scaled raw overflows QuantityRaw // after assert!(qty_a.precision <= FIXED_PRECISION && qty_b.precision <= FIXED_PRECISION); let c = qty_a * qty_b;
Defensive patterns
Strategy: validation
Validate before calling
fn can_mul(a: &Quantity, b: &Quantity) -> bool {
a.precision <= FIXED_PRECISION
&& b.precision <= FIXED_PRECISION
&& a.raw.checked_mul(b.raw).map(|r| r <= QUANTITY_RAW_MAX).unwrap_or(false)
} Type guard
fn precision_in_range(q: &Quantity) -> bool { q.precision <= FIXED_PRECISION } Try / catch
// Rust panics are not catchable via Result; use catch_unwind if absolutely required let result = std::panic::catch_unwind(|| a * b);
Prevention
- Keep quantity precisions within FIXED_PRECISION when constructing instruments
- Use Quantity::new_checked for conversions from raw values
- Bound operand magnitudes before multiplicative composition
When it happens
Trigger: Calling Quantity::mul (the `*` operator) on two Quantity values whose precision exceeds FIXED_PRECISION, so the else branch computes raw_scale(min(precision)) and the scaled divisor overflows QuantityRaw::try_from.
Common situations: Quantities constructed with very high precision (e.g. from exotic instrument definitions or misparsed instrument definitions with precision above the fixed-point limit), or a bug/overflow in raw_scale for the given precision.
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
- Overflow when scaling f64 to fixed-point i64
- Overflow when scaling f64 to fixed-point i128
- Overflow when scaling f64 to fixed-point u64
- Overflow when scaling f64 to fixed-point u128
- Overflow occurred when multiplying `Quantity`
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/3e33e120daf6ace5.
Report an issue: GitHub.