nautechsystems/nautilus_trader · error

Decimal exponent {exponent} exceeds supported maximum {DECIM

Error message

Decimal exponent {exponent} exceeds supported maximum {DECIMAL_EXPONENT_MAX}

What it means

`check_decimal_exponent` validates that a decimal exponent (number of fractional digits to represent) does not exceed `DECIMAL_EXPONENT_MAX`, the largest power of ten the tick-map math supports. The library throws this when a token's decimals or a requested exponent exceeds that cap.

Source

Thrown at crates/model/src/defi/tick_map/full_math.rs:142

        let mut quotient = Self::mul_div(a, b, denominator)?;
        let mut remainder = a.mul_mod(b, denominator);

        for &scale in scales {
            let scaled_quotient = quotient
                .checked_mul(scale)
                .ok_or_else(|| anyhow::anyhow!("Scaled result exceeds 256-bit range"))?;
            let scaled_remainder = Self::mul_div(remainder, scale, denominator)?;
            quotient = scaled_quotient
                .checked_add(scaled_remainder)
                .ok_or_else(|| anyhow::anyhow!("Scaled result exceeds 256-bit range"))?;
            remainder = remainder.mul_mod(scale, denominator);
        }

        Ok(quotient)
    }

    pub(crate) fn check_decimal_exponent(exponent: u8) -> anyhow::Result<()> {
        anyhow::ensure!(
            exponent <= DECIMAL_EXPONENT_MAX,
            "Decimal exponent {exponent} exceeds supported maximum {DECIMAL_EXPONENT_MAX}"
        );
        Ok(())
    }

    pub(crate) fn pow10(exponent: u8) -> anyhow::Result<U256> {
        Self::check_decimal_exponent(exponent)?;
        U256::from(10)
            .checked_pow(U256::from(exponent))
            .ok_or_else(|| anyhow::anyhow!("Decimal exponent {exponent} exceeds U256 range"))
    }

    /// Calculates ceil(a×b÷denominator) with full precision
    /// Returns `Ok` with the rounded result or an error when rounding cannot be performed safely.
    ///
    /// # Errors
    ///

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Cap or reject the token: check `decimals <= DECIMAL_EXPONENT_MAX` when loading token metadata.
  2. Re-fetch correct token decimals from a trusted source (on-chain call, token list).
  3. If the exponent comes from config, validate/clamp it at load time.
  4. Extend DECIMAL_EXPONENT_MAX only if the surrounding math is proven safe.

Example fix

// before
let factor = pow10(token.decimals)?;
// after
ensure!(token.decimals <= DECIMAL_EXPONENT_MAX, "unsupported token decimals {}", token.decimals);
let factor = pow10(token.decimals)?;
Defensive patterns

Strategy: validation

Validate before calling

fn valid_decimals(d: u8) -> bool { d <= DECIMAL_EXPONENT_MAX }

Type guard

fn is_supported_exponent(e: u8) -> bool { e <= DECIMAL_EXPONENT_MAX }

Try / catch

match pow10(exponent) {
    Ok(v) => v,
    Err(e) if e.to_string().contains("exceeds supported maximum") => {
        log::warn!("unsupported decimal exponent {exponent}"); U256::one()
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `check_decimal_exponent` or its callers (`pow10`, price decoding paths) with an exponent greater than DECIMAL_EXPONENT_MAX — e.g. tokens with unusually high decimal counts or misparsed decimals metadata.

Common situations: Token metadata from an unknown/nonstandard chain reporting decimals above the supported maximum; a config value or ABI-decoded field containing garbage that lands in the exponent slot.

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