nautechsystems/nautilus_trader · warning

effective raw scale should fit in MoneyRaw

Error message

effective raw scale should fit in MoneyRaw

What it means

Money's Python __int__ divides the internal raw fixed-precision integer by the raw scale derived from the currency's precision, computing that scale with PriceRaw/MoneyRaw::try_from and expecting it to always fit. This is a can't-happen guard; it panics only if the effective scale exceeds the MoneyRaw integer type, implying a currency precision outside supported bounds.

Source

Thrown at crates/model/src/python/types/money.rs:389

            )))
        }
    }

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

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

    fn __abs__(&self) -> Self {
        if self.raw < 0 { -*self } else { *self }
    }

    fn __int__(&self) -> MoneyRaw {
        let scale = MoneyRaw::try_from(raw_scale(self.currency.precision))
            .expect("effective raw scale should fit in MoneyRaw");
        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. Verify the currency's precision is a valid 0..=supported-max value (use Currency::new with sane precision)
  2. Avoid int() on suspect Money values; use float(money) / as_f64 or money.formatted() instead
  3. Fix the currency registration source (metadata feed, config) rather than the conversion call site

Example fix

// before
units = int(money)
// after
assert 0 <= money.currency.precision <= 16, "invalid currency precision"
units = int(money)
Defensive patterns

Strategy: type-guard

Validate before calling

# Python
assert 0 <= money.currency.precision <= 16, "invalid currency precision"
units = int(money)

Type guard

def safe_int(m: Money) -> int | None:
    return int(m) if 0 <= m.currency.precision <= 16 else None

Try / catch

try:
    units = int(money)
except Exception:
    units = None  # fall back to float(money)

Prevention

When it happens

Trigger: Calling int(money) on a Money whose currency precision implies a raw_scale that doesn't fit MoneyRaw — only possible with an invalid/corrupt currency definition precision.

Common situations: Custom Currency registered with a bogus precision (negative or beyond max supported); a bug in currency construction rather than normal use; passing raw ints as precision when building currencies from external metadata.

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/40efdffe78633605. Report an issue: GitHub.