nautechsystems/nautilus_trader · error · anyhow::Error

Order amount overflow scaling quantity to raw token units

Error message

Order amount overflow scaling quantity to raw token units

What it means

Second overflow guard on the same branch of quantity_to_raw_amount: after computing the scale factor successfully, raw * scale is checked. This fires when the order quantity, in fixed-point raw units, is so large that shifting it up to the token's decimals overflows U256.

Source

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

/// Converts a base-denominated order quantity into raw token units with exact integer
/// scaling by the base token decimals.
///
/// `Quantity::raw` is scaled to the greater of its declared precision and `FIXED_PRECISION`;
/// token amounts are scaled to the token's decimals. Quantities not exactly representable in
/// token units are rejected rather than rounded.
fn quantity_to_raw_amount(quantity: Quantity, decimals: u8) -> anyhow::Result<U256> {
    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)
    }
}

/// Extracts the positive output amount from an exact-input swap quote.
fn exact_output_amount(quote: &SwapQuote, zero_for_one: bool) -> anyhow::Result<U256> {
    let amount = if zero_for_one {
        quote.amount1

View on GitHub (pinned to 2114cf6f76)

Solutions

  1. Log the quantity, its precision, and the token decimals at order construction and sanity-check the implied whole-token amount.
  2. Cap order size against the wallet balance and the token's total supply.
  3. Fix the sizing unit confusion (whole tokens vs raw fixed-point).
  4. Reject at the strategy layer with a clear message before submission.
Defensive patterns

Strategy: validation

Validate before calling

// bound the implied whole-token amount before submission
let max_units = U256::from(10u64).pow(U256::from(token.decimals + 18)); // 1e18 whole tokens ceiling
if quantity_to_raw_amount(qty, token.decimals)? > max_units {
    anyhow::bail!("order size implausibly large for {}", token.symbol);
}

Try / catch

Catch the overflow, reject the order at the strategy layer with an explicit size message, and do not resubmit the same quantity.

Prevention

When it happens

Trigger: An enormous order quantity (e.g., more than ~10^59 base units) combined with high token decimals; a fat-fingered or unit-confused quantity (treating whole tokens as raw fixed-point units or vice versa); quantity constructed with the wrong precision.

Common situations: Strategy sizing computed against the wrong token (18-decimals quantity applied to a 36-decimals token); copy-paste of amounts between instruments; unbounded position sizing feeding straight into submit_order.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@2114cf6f76 (2026-08-21). Data as JSON: /api/errors/a760ea030f3e2364. Report an issue: GitHub.