nautechsystems/nautilus_trader · error

Order quantity {quantity} is not exactly representable in {d

Error message

Order quantity {quantity} is not exactly representable in {decimals} base token decimals

What it means

When the quantity's raw precision exceeds the token's decimals, the raw amount must be divisible by 10^(raw_precision - decimals) to map exactly onto token units. If not, the conversion would require rounding, which is rejected to preserve exact discrete values, and this error names the offending quantity and decimals.

Source

Thrown at crates/adapters/blockchain/src/execution/client.rs:5220

    if quantity.is_zero() {
        anyhow::bail!("Order quantity must be positive");
    }

    let raw = U256::from(quantity.raw);
    let raw_precision = quantity.precision.max(FIXED_PRECISION);
    if decimals >= raw_precision {
        let scale = U256::from(10u64)
            .checked_pow(U256::from(decimals - raw_precision))
            .ok_or_else(|| anyhow::anyhow!("Order amount scaling overflow"))?;
        raw.checked_mul(scale).ok_or_else(|| {
            anyhow::anyhow!("Order amount overflow scaling quantity to raw token units")
        })
    } else {
        let divisor = U256::from(10u64)
            .checked_pow(U256::from(raw_precision - decimals))
            .ok_or_else(|| anyhow::anyhow!("Order amount scaling overflow"))?;
        if !(raw % divisor).is_zero() {
            anyhow::bail!(
                "Order quantity {quantity} is not exactly representable in {decimals} base token decimals"
            );
        }
        Ok(raw / divisor)
    }
}

fn swap_token_pair(
    side: OrderSide,
    base: Address,
    quote: Address,
) -> anyhow::Result<(Address, Address)> {
    match side {
        OrderSide::Sell => Ok((base, quote)),
        OrderSide::Buy => Ok((quote, base)),
    }
}

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Round the order quantity down to a value representable in the token's decimals before conversion
  2. Correct the instrument definition so its size precision does not exceed the token's decimals
  3. Fix upstream sizing math to quantize to the token's decimal grid
  4. Verify the token decimals value passed in matches the actual contract

Example fix

// before: passing raw computed size
let qty = Quantity::new(notional / price, 9);
let raw = quantity_to_raw_amount(qty, decimals)?;
// after: quantize to token decimals first
let step = 10f64.powi(-(decimals as i32));
let qty = Quantity::new((notional / price).floor_to(step), decimals as u8);
let raw = quantity_to_raw_amount(qty, decimals)?;
Defensive patterns

Strategy: validation

Validate before calling

fn is_representable(raw: &U256, raw_precision: u8, decimals: u8) -> bool {
    if decimals >= raw_precision { return true; }
    let div = U256::from(10u64).pow(U256::from(raw_precision - decimals));
    (raw % div).is_zero()
}

Try / catch

match res {
    Err(e) if e.to_string().contains("not exactly representable") => {
        let qty = quantize_to_decimals(quantity, decimals);
        quantity_to_raw_amount(qty, decimals)?
    }
    other => other?,
}

Prevention

When it happens

Trigger: Converting an order Quantity whose raw value has sub-base-unit precision (e.g. raw precision 9 with a token using 6 decimals) where quantity.raw is not divisible by 10^(raw_precision - decimals) — e.g. quantity 1.0000005 on a 6-decimal token.

Common situations: Instrument price/size precision configured finer than the token's decimals; quantities generated from USD-notional math at higher precision; a mismatch between the instrument definition's precision and the actual token contract decimals.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/d990b3d6e2504438. Report an issue: GitHub.