nautechsystems/nautilus_trader · warning

Executed amount {amount} is below representable quantity pre

Error message

Executed amount {amount} is below representable quantity precision {FIXED_PRECISION}

What it means

After scaling the raw U256 amount into a Quantity, the adapter checks the result is nonzero. If the raw amount is smaller than one unit of the representable fixed-point precision (FIXED_PRECISION), the quantity truncates to zero and the adapter bails rather than propagate a zero executed quantity.

Source

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

    Price::from_decimal_dp(quote.as_decimal() / last_qty.as_decimal(), FIXED_PRECISION)
        .map_err(anyhow::Error::from)
}

fn raw_amount_to_quantity(amount: U256, decimals: u8) -> anyhow::Result<Quantity> {
    if amount.is_zero() {
        anyhow::bail!("Executed amount must be positive");
    }
    let quantity = if decimals >= FIXED_PRECISION {
        let scale = U256::from(10u64)
            .checked_pow(U256::from(decimals - FIXED_PRECISION))
            .ok_or_else(|| anyhow::anyhow!("Executed amount scaling overflow"))?;
        Quantity::from_u256(amount / scale, FIXED_PRECISION).map_err(anyhow::Error::from)?
    } else {
        Quantity::from_u256(amount, decimals).map_err(anyhow::Error::from)?
    };

    if quantity.is_zero() {
        anyhow::bail!(
            "Executed amount {amount} is below representable quantity precision {FIXED_PRECISION}"
        );
    }
    Ok(quantity)
}

fn exact_output_amount(quote: &SwapQuote, zero_for_one: bool) -> anyhow::Result<U256> {
    let amount = if zero_for_one {
        quote.amount1
    } else {
        quote.amount0
    };

    if !amount.is_negative() {
        anyhow::bail!("Swap quote output amount {amount} is not a positive output");
    }
    Ok(amount.unsigned_abs())
}

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the token decimals configured match the actual on-chain token
  2. Treat the execution as dust: skip it rather than erroring, or accumulate amounts before converting
  3. If the fill is real and important, check for a decimals/parsing bug upstream

Example fix

// before
let qty = raw_amount_to_quantity(amount, decimals)?;
// after
if amount < U256::from(10u64).pow(decimals.into()) {
    tracing::warn!("dust execution {} below precision, skipping", amount);
    return Ok(None);
}
let qty = raw_amount_to_quantity(amount, decimals)?;
Defensive patterns

Strategy: validation

Validate before calling

let scale = U256::from(10u64).pow(U256::from(decimals));
if amount < scale {
    tracing::warn!("amount {amount} below 1 unit at {decimals} decimals; treating as dust");
    return Ok(None);
}

Try / catch

match raw_amount_to_quantity(amount, decimals) {
    Ok(q) => handle(q),
    Err(e) if e.to_string().contains("below representable") => handle_dust(amount),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: raw_amount_to_quantity receives a tiny raw amount (e.g. 1..scale-1 wei) with token decimals >= FIXED_PRECISION, so amount/scale rounds to zero.

Common situations: Dust fills/swaps on high-decimals tokens; token decimals misconfigured so scale is much larger than expected.

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