nautechsystems/nautilus_trader · error

quantity for {currency} overflowed while increasing raw scal

Error message

quantity for {currency} overflowed while increasing raw scale

What it means

When the quantity's source precision is lower than the target (currency/FIXED) precision, the raw value is scaled up by 10^(target-source) using checked_mul. If that multiplication overflows i128, this error is thrown instead of silently wrapping.

Source

Thrown at crates/portfolio/src/manager.rs:1427

#[allow(
    clippy::useless_conversion,
    reason = "the raw width differs when high-precision is disabled"
)]
fn wallet_money_from_quantity(quantity: Quantity, currency: Currency) -> anyhow::Result<Money> {
    anyhow::ensure!(!quantity.is_undefined(), "quantity was undefined");
    Quantity::from_raw_checked(quantity.raw, quantity.precision)?;
    check_fixed_raw_u128(u128::from(quantity.raw), quantity.precision)?;

    let source_precision = quantity.precision.max(FIXED_PRECISION);
    let target_precision = currency.precision.max(FIXED_PRECISION);
    let raw = i128::try_from(u128::from(quantity.raw))
        .map_err(|_| anyhow::anyhow!("quantity for {currency} exceeds signed raw bounds"))?;
    let raw = match source_precision.cmp(&target_precision) {
        Ordering::Less => {
            let scale = 10_i128.pow(u32::from(target_precision - source_precision));
            raw.checked_mul(scale).ok_or_else(|| {
                anyhow::anyhow!("quantity for {currency} overflowed while increasing raw scale")
            })?
        }
        Ordering::Greater => {
            let scale = 10_i128.pow(u32::from(source_precision - target_precision));
            anyhow::ensure!(
                raw % scale == 0,
                "quantity for {currency} loses precision when decreasing raw scale"
            );
            raw / scale
        }
        Ordering::Equal => raw,
    };
    check_fixed_raw_i128(raw, currency.precision)?;
    let raw: MoneyRaw = raw
        .try_into()
        .map_err(|_| anyhow::anyhow!("quantity for {currency} exceeds Money raw bounds"))?;

    Money::from_raw_checked(raw, currency).map_err(Into::into)

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify currency precision is configured correctly for the asset
  2. Keep quantity precision aligned with currency precision to avoid scaling
  3. Reduce the quantity magnitude (data likely corrupted if balance is astronomically large)
  4. Add checked arithmetic guards in strategy code before reporting balances

Example fix

// before
currency = Currency::from("SHIB"); // precision 12
qty = Quantity::from_raw(u64::MAX, 0); // scaling overflows
// after
qty = Quantity::new(1_000.0, currency.precision); // precision matches; no scaling
Defensive patterns

Strategy: validation

Validate before calling

let scale = 10_i128.pow((currency.precision.max(FIXED_PRECISION) - quantity.precision) as u32);
let raw = i128::try_from(u128::from(quantity.raw)).unwrap();
anyhow::ensure!(raw.checked_mul(scale).is_some(), "scaling would overflow; reduce quantity or precision");

Try / catch

manager.update_balance_locked_wallet(&id, currency, quantity)
    .map_err(|e| anyhow::anyhow!("wallet lock failed for {currency}: {e}"))?;

Prevention

When it happens

Trigger: Converting a quantity whose precision is lower than the currency's precision while its raw value is large enough that raw * 10^scale exceeds i128 bounds.

Common situations: Currency precision set higher than instrument precision with large balances; misconfigured currency precision (e.g. precision 9-12 crypto tokens) combined with huge raw quantities.

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