nautechsystems/nautilus_trader · error
Scale 10^{} exceeds U256 while converting {type_name}
Error message
Scale 10^{} exceeds U256 while converting {type_name} What it means
scale_u256_to_raw computes 10^(fixed_precision − decimals) as a U256 power when decimals < fixed_precision. If checked_pow overflows U256, the exponent is impossibly large and the conversion aborts with this message naming the type being converted (e.g. 'Quantity' or 'Price').
Source
Thrown at crates/adapters/blockchain/src/decode.rs:100
)?;
let raw = PriceRaw::try_from(raw)
.map_err(|e| anyhow::anyhow!("Failed to convert Price raw value: {e}"))?;
Ok(Price::from_raw_checked(raw, precision)?)
}
fn scale_u256_to_raw(
amount: U256,
decimals: u8,
fixed_precision: u8,
raw_max: U256,
type_name: &str,
raw_max_name: &str,
) -> anyhow::Result<U256> {
let raw = if decimals < fixed_precision {
let scale = U256::from(10)
.checked_pow(U256::from(fixed_precision - decimals))
.ok_or_else(|| {
anyhow::anyhow!(
"Scale 10^{} exceeds U256 while converting {type_name}",
fixed_precision - decimals
)
})?;
amount.checked_mul(scale).ok_or_else(|| {
anyhow::anyhow!(
"{type_name} amount {amount} overflows U256 while scaling from {decimals} to {fixed_precision} decimals"
)
})?
} 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)
}View on GitHub (pinned to 18893faf8b)
Solutions
- Verify the decimals argument — fetch ERC20.decimals() on-chain rather than hardcoding 0.
- Sanity-check decimals ∈ 0..=18 (typical token range) before calling the conversion.
- If decimals is genuinely tiny and the value huge, the amount exceeds domain representability; handle at a higher level.
- Trace the value source: a decoded-decimals of 0 often indicates a wrong ABI or failed static call defaulting to zero.
Example fix
// before let qty = u256_to_quantity(amount, 0, FIXED_PRECISION)?; // after let decimals = token.decimals().call().await?; // e.g. 6 or 18 debug_assert!(decimals <= 18); let qty = u256_to_quantity(amount, decimals, FIXED_PRECISION)?;
Defensive patterns
Strategy: validation
Validate before calling
// reject implausible decimals before scaling
fn sane_decimals(d: u8) -> Result<u8, String> {
match d {
0..=18 => Ok(d),
other => Err(format!("implausible token decimals: {other}")),
}
} Type guard
fn plausible_decimals(d: u8) -> bool {
d <= 18
} Prevention
- Always fetch ERC20.decimals() from chain; never hardcode 0
- Validate decimals is within the realistic 0–18 range before conversion
- A decoded decimals of 0 usually signals a wrong ABI or failed static call — investigate upstream
When it happens
Trigger: Calling u256_to_quantity/u256_to_price with a decimals value drastically smaller than the fixed precision, such that 10^(fixed_precision − decimals) cannot even be represented in U256 (exponent ≳ 78).
Common situations: Passing decimals=0 or garbage decimals (e.g. a u8::MAX sentinel or uninitialized value) for tokens that actually have 6–18 decimals; mis-wired ABI decoding returning 0 for decimals.
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
- WETH balance overflow for included transaction {tx_hash} at
- Result would overflow 256 bits
- Failed to convert Quantity raw value: {e}
- Failed to convert Price raw value: {e}
- {type_name} amount {amount} overflows U256 while scaling fro
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/c59ef92f9d2a34fe.
Report an issue: GitHub.