nautechsystems/nautilus_trader · error

effective raw scale should fit in QuantityRaw

Error message

effective raw scale should fit in QuantityRaw

What it means

Quantity's `__int__` (Python int() conversion) truncates the raw fixed-point value by dividing by 10^precision. The scale constant 10^precision is first converted into QuantityRaw (an i64/u64), and if the effective scale does not fit in that integer type the conversion fails and this panic is thrown. It guards an internal invariant of the fixed-point representation.

Source

Thrown at crates/model/src/python/types/quantity.rs:398

            )))
        }
    }

    fn __neg__(&self) -> Decimal {
        self.as_decimal().neg()
    }

    fn __pos__(&self) -> Self {
        *self
    }

    fn __abs__(&self) -> Self {
        *self
    }

    fn __int__(&self) -> QuantityRaw {
        let scale = QuantityRaw::try_from(raw_scale(self.precision))
            .expect("effective raw scale should fit in QuantityRaw");
        self.raw / scale
    }

    fn __float__(&self) -> f64 {
        self.as_f64()
    }

    #[pyo3(signature = (ndigits=None))]
    fn __round__(&self, ndigits: Option<u32>) -> Decimal {
        self.as_decimal()
            .round_dp_with_strategy(ndigits.unwrap_or(0), RoundingStrategy::MidpointNearestEven)
    }

    fn __repr__(&self) -> String {
        format!("{self:?}")
    }

    fn __str__(&self) -> String {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Lower the precision used for the Quantity so 10^precision fits in QuantityRaw.
  2. Use as_f64()/float() conversion instead of int() for high-precision quantities.
  3. If high precision is genuinely needed, ensure the build uses the high-precision (i128) feature so QuantityRaw is wide enough.

Example fix

// before
q = Quantity.from_raw(123456789012345678901, precision=25)
print(int(q))  # panics
// after
q = Quantity.from_raw(123456789012345678901, precision=25)
print(int(float(q)))  # truncate via float, or use a lower precision
Defensive patterns

Strategy: validation

Validate before calling

# Python side
if quantity.precision > 18:  # 10**18 is near QuantityRaw (i64) limit
    raise ValueError("precision too high for int() conversion")
int(quantity)

Type guard

def safe_int(q) -> int | None:
    return None if q.precision > 18 else int(q)

Prevention

When it happens

Trigger: Calling int(quantity) on a Quantity whose currency/price precision implies a raw scale (10^precision) larger than QuantityRaw::MAX, e.g. a very high precision value exposed through the Python bindings.

Common situations: Using extreme precision values (near or above the i64/u64 digit limit ~18-19 digits) when constructing instruments or prices, then converting to int in Python; test fixtures with unrealistic precision settings.

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/686aa4e398e58e25. Report an issue: GitHub.