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
- Cap or reject the token: check `decimals <= DECIMAL_EXPONENT_MAX` when loading token metadata.
- Re-fetch correct token decimals from a trusted source (on-chain call, token list).
- If the exponent comes from config, validate/clamp it at load time.
- 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
- Validate token decimals when loading token metadata, rejecting unsupported tokens early
- Sanitize ABI-decoded decimals fields (cap at 36 for standard EVM tokens)
- Keep DECIMAL_EXPONENT_MAX visible in config validation messages
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
- Order quantity {quantity} is not exactly representable in {d
- Quote spend limit decimals do not match the deployment manif
- Scaled result exceeds 256-bit range
- Decimal exponent {exponent} exceeds U256 range
- Unsupported `OrderSide` for Binance: {value:?}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/fc3f5d0e3637b484.
Report an issue: GitHub.