nautechsystems/nautilus_trader · error

{type_name} raw value {raw} exceeds {raw_max_name}={raw_max}

Error message

{type_name} raw value {raw} exceeds {raw_max_name}={raw_max}

What it means

check_raw_range validates that a U256 raw value fits within a maximum representable value for a target type (Quantity, Price, or a scaled raw representation) and bails when raw > raw_max. This guards fixed-point conversions from silently wrapping or truncating when a decoded on-chain value exceeds the type's precision/width.

Source

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

        })?
    } else if decimals > fixed_precision {
        round_u256_half_even(amount, decimals - fixed_precision, type_name)?
    } else {
        amount
    };

    check_raw_range(raw, raw_max, type_name, raw_max_name)?;
    Ok(raw)
}

fn check_raw_range(
    raw: U256,
    raw_max: U256,
    type_name: &str,
    raw_max_name: &str,
) -> anyhow::Result<()> {
    if raw > raw_max {
        anyhow::bail!("{type_name} raw value {raw} exceeds {raw_max_name}={raw_max}");
    }

    Ok(())
}

fn round_u256_half_even(amount: U256, excess: u8, type_name: &str) -> anyhow::Result<U256> {
    let Some(divisor) = U256::from(10).checked_pow(U256::from(excess)) else {
        // The divisor exceeds U256::MAX, so every U256 amount is below half a retained unit
        return Ok(U256::ZERO);
    };
    let quotient = amount / divisor;
    let remainder = amount % divisor;
    let half = divisor / U256::from(2);

    if remainder > half || (remainder == half && quotient.bit(0)) {
        quotient.checked_add(U256::from(1)).ok_or_else(|| {
            anyhow::anyhow!("{type_name} raw value overflows U256 while rounding half to even")
        })

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the magnitude of the on-chain value before conversion and skip/reject out-of-range values
  2. Verify the token's decimals and use a precision for the target type large enough for real values
  3. Treat the offending log as malformed: log the tx/log id and exclude it from processing
  4. Use U256-native or higher-precision types if your assets legitimately exceed the raw max

Example fix

// before: unchecked conversion of log amount
let qty = u256_to_quantity(raw_amount, decimals, precision)?;
// after: pre-check range
let raw_max = max_raw_for_precision(precision);
if raw_amount > raw_max {
    tracing::warn!("skipping amount exceeding raw max: {raw_amount}");
    return Ok(None);
}
let qty = u256_to_quantity(raw_amount, decimals, precision)?;
Defensive patterns

Strategy: validation

Validate before calling

let raw_max = max_raw_for_precision(precision);
if raw_amount > raw_max {
    return Ok(None); // skip out-of-range value
}

Type guard

fn fits_raw_max(raw: U256, raw_max: U256) -> bool { raw <= raw_max }

Try / catch

match u256_to_quantity(raw_amount, decimals, precision) {
    Ok(q) => Some(q),
    Err(e) if e.to_string().contains("exceeds") => {
        tracing::warn!("amount {raw_amount} exceeds raw max; skipping log");
        None
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling u256_to_quantity, u256_to_price, or scale_u256_to_raw with a decoded U256 (from an event log, reserves, or amounts) whose integer value exceeds the maximum raw value allowed by the target type's precision.

Common situations: Tokens with extreme supply/decimals producing amounts beyond the fixed-point raw max; malformed or malicious log data with huge values; decoding a non-standard token's balance/amount events with the standard decoder; scaling between precisions where the intermediate raw overflows the cap.

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