nautechsystems/nautilus_trader · error · anyhow::Error
Result would overflow 256 bits
Error message
Result would overflow 256 bits
What it means
mul_div computes floor(a*b/denominator) with full 512-bit intermediate precision. If the 512-bit product's high word is >= the denominator, the quotient would exceed 256 bits, so the function bails instead of returning a wrapped result. This also implicitly rejects denominator == 0.
Source
Thrown at crates/model/src/defi/tick_map/full_math.rs:52
/// # Errors
///
/// Returns error if `denominator` is zero or the result would overflow 256 bits.
pub fn mul_div(a: U256, b: U256, mut denominator: U256) -> anyhow::Result<U256> {
// 512-bit multiply [prod1 prod0] = a * b
// Compute the product mod 2**256 and mod 2**256 - 1
// then use the Chinese Remainder Theorem to reconstruct
// the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2**256 + prod0
let mm = a.mul_mod(b, U256::MAX);
// Least significant 256 bits of the product
let mut prod_0 = a * b;
let mut prod_1 = mm - prod_0 - U256::from_limbs([u64::from(mm < prod_0), 0, 0, 0]);
// Make sure the result is less than 2**256.
// Also prevents denominator == 0
if denominator <= prod_1 {
anyhow::bail!("Result would overflow 256 bits");
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0]
// Compute remainder using mul_mod
let remainder = a.mul_mod(b, denominator);
// Subtract 256 bit number from 512 bit number
prod_1 -= U256::from_limbs([u64::from(remainder > prod_0), 0, 0, 0]);
prod_0 -= remainder;
// Factor powers of two out of denominator
// Compute largest power of two divisor of denominator.
// Always >= 1.
let mut twos = (-denominator) & denominator;View on GitHub (pinned to 18893faf8b)
Solutions
- Reduce a or b before multiplying (factor out common terms with the denominator)
- Validate inputs so a*b/denominator fits in U256 before calling
- Treat denominator == 0 separately and reject it at the call site
- Match Uniswap's solidity behavior: this error mirrors the 'mulDiv overflow' revert
Example fix
// before let out = mul_div(a, b, denom)?; // after anyhow::ensure!(!denom.is_zero(), "denominator must be non-zero"); let out = mul_div(a, b, denom)?; // now only genuine overflow remains possible
Defensive patterns
Strategy: try-catch
Validate before calling
fn mul_div_fits(a: U256, b: U256, denom: U256) -> bool {
!denom.is_zero() && a.checked_mul(b).map(|p| p / denom < U256::MAX).unwrap_or(false)
} Try / catch
let out = mul_div(a, b, denom)
.map_err(|e| MyError::MathOverflow(e.to_string()))?; Prevention
- Reject zero denominators before calling
- Normalize or reduce amounts before multiplying large values
- Port tests from Uniswap FullMath edge cases
When it happens
Trigger: Calling mul_div(a, b, denominator) where a*b/denominator >= 2**256 — very large a and b relative to denominator, or denominator zero (which makes prod_1 compare true).
Common situations: Tick/liquidity math on adversarial or corrupted inputs; ported Uniswap V3 FullMath behavior when scaling amounts with extreme ratios; forgetting to normalize amounts before multiplication.
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
- Cannot divide by zero
- DurationNanos overflow in from_micros
- {e}
- Estimated gas {estimate} with {gas_buffer_bps} bps buffer ({
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/2749810f7be05ec5.
Report an issue: GitHub.