nautechsystems/nautilus_trader · error

Failed to convert Quantity raw value: {e}

Error message

Failed to convert Quantity raw value: {e}

What it means

u256_to_quantity scales a U256 amount by the token decimals to the Quantity fixed precision, then converts to QuantityRaw (the domain raw i128-style representation) via TryFrom. If the scaled value does not fit into QuantityRaw, the conversion fails and is wrapped with this message. The bounded domain checks (QUANTITY_RAW_MAX) have already passed, so this fires on a TryFrom narrowing failure.

Source

Thrown at crates/adapters/blockchain/src/decode.rs:54

            amount,
            U256::from(QUANTITY_RAW_MAX),
            "Quantity",
            "QUANTITY_RAW_MAX",
        )?;
        return Ok(Quantity::from_wei(amount));
    }

    let precision = decimals.min(FIXED_PRECISION);
    let raw = scale_u256_to_raw(
        amount,
        decimals,
        FIXED_PRECISION,
        U256::from(QUANTITY_RAW_MAX),
        "Quantity",
        "QUANTITY_RAW_MAX",
    )?;
    let raw = QuantityRaw::try_from(raw)
        .map_err(|e| anyhow::anyhow!("Failed to convert Quantity raw value: {e}"))?;
    Ok(Quantity::from_raw_checked(raw, precision)?)
}

/// Convert a `U256` amount to [`Price`].
///
/// - If `decimals == 18`, the value represents wei and uses the dedicated lossless
///   `Price::from_wei` constructor.
/// - Other precisions use checked integer scaling and clamp `decimals` to
///   [`FIXED_PRECISION`]. Discarded source digits are rounded half to even.
///
/// # Errors
///
/// Returns an error if scaling overflows or the result exceeds [`PRICE_RAW_MAX`].
pub fn u256_to_price(amount: U256, decimals: u8) -> anyhow::Result<Price> {
    if decimals == 18 {
        check_raw_range(amount, U256::from(PRICE_RAW_MAX), "Price", "PRICE_RAW_MAX")?;
        return Ok(Price::from_wei(amount));
    }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the token's decimals value passed to u256_to_quantity matches the on-chain token decimals.
  2. Range-check the scaled amount against QuantityRaw::MAX (QUANTITY_RAW_MAX) before conversion.
  3. If the balance genuinely exceeds the domain max, the value cannot be represented as a Nautilus Quantity — handle/scale at a higher level.
  4. Check that the raw value was not multiplied twice (e.g. already-adjusted wei passed with decimals=0).

Example fix

// before
let qty = u256_to_quantity(raw_balance, 0)?; // decimals guessed wrong

// after
let decimals = erc20.decimals().call().await?; // fetch on-chain decimals
let qty = u256_to_quantity(raw_balance, decimals)?;
Defensive patterns

Strategy: validation

Validate before calling

// precondition check before conversion
let scale = 10u32.checked_pow(FIXED_PRECISION - decimals)
    .ok_or("scale overflow")?;
let scaled = amount.checked_mul(U256::from(scale))
    .ok_or("amount overflow")?;
assert!(scaled <= U256::from(QUANTITY_RAW_MAX), "exceeds QUANTITY_RAW_MAX");

Type guard

fn fits_quantity_raw(v: U256) -> bool {
    v <= U256::from(QUANTITY_RAW_MAX)
}

Prevention

When it happens

Trigger: Converting a U256 token amount whose scaled raw value (amount × 10^(fixed_precision − decimals)) exceeds the QuantityRaw integer type's maximum — extremely large token balances or precision mismatches.

Common situations: Tokens with very few decimals (0–6) holding enormous supplies; decoding raw values mis-scaled by passing the wrong decimals for the token; contract responses read with wrong ABI scale.

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