nautechsystems/nautilus_trader · error

Cannot decode inverted price from zero sqrt_price_x96

Error message

Cannot decode inverted price from zero sqrt_price_x96

What it means

In the inverted price branch (decimal_diff < 0), the denominator is sqrt_price_x96^2. A zero sqrt_price_x96 would mean division by zero, so the function explicitly rejects it with this error. Uniswap V3 pools can transiently report sqrt_price_x96 == 0 (empty/liquidity-less pool state), which makes an inverted token0/token1 price mathematically undefined.

Source

Thrown at crates/model/src/defi/tick_map/sqrt_price_math.rs:416

            if price_square > max_square {
                U256::ZERO
            } else {
                let price_square = U256::checked_from_limbs_slice(price_square.as_limbs())
                    .ok_or_else(|| {
                        anyhow::anyhow!("Inverted price denominator exceeds U256 range")
                    })?;
                let denominator =
                    price_square
                        .checked_mul(decimal_adjustment)
                        .ok_or_else(|| {
                            anyhow::anyhow!("Inverted price denominator exceeds U256 range")
                        })?;
                FullMath::mul_div(numerator, U256::from(1), denominator)?
            }
        } else {
            let price_square: U512 = sqrt_price.widening_mul(sqrt_price);
            anyhow::ensure!(
                !price_square.is_zero(),
                "Cannot decode inverted price from zero sqrt_price_x96"
            );
            let numerator = U512::from(divisor_base)
                .checked_mul(U512::from(decimal_adjustment))
                .and_then(|value| value.checked_mul(U512::from(fixed_scalar)))
                .ok_or_else(|| anyhow::anyhow!("Inverted price numerator exceeds U512 range"))?;
            let quotient = numerator / price_square;
            U256::checked_from_limbs_slice(quotient.as_limbs())
                .ok_or_else(|| anyhow::anyhow!("Inverted price exceeds U256 range"))?
        }
    } else if decimal_diff >= 0 {
        FullMath::mul_div_scaled(
            sqrt_price,
            sqrt_price,
            divisor_base,
            &[fixed_scalar, decimal_adjustment],
        )?

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check sqrt_price_x96 != 0 before calling and skip the pool or default the price to zero.
  2. Handle the error by treating the pool as unpriced (no liquidity) rather than retrying.
  3. If a price is required, wait until the pool has been initialized (slot0.sqrtPriceX96 > 0).

Example fix

// before
let price = decode_sqrt_price_x96_to_price_tokens_adjusted(sqrt_price_x96, d0, d1, true)?;
// after
if sqrt_price_x96.is_zero() {
    // unpriced/uninitialized pool
    return Ok(Price::zero(FIXED_PRECISION));
}
let price = decode_sqrt_price_x96_to_price_tokens_adjusted(sqrt_price_x96, d0, d1, true)?;
Defensive patterns

Strategy: validation

Validate before calling

if sqrt_price_x96.is_zero() { return Ok(Price::zero(FIXED_PRECISION)); }

Type guard

fn pool_is_priced(sqrt_price_x96: U160) -> bool { !sqrt_price_x96.is_zero() }

Try / catch

match decode_sqrt_price_x96_to_price_tokens_adjusted(sp, d0, d1, true) {
    Ok(p) => p,
    Err(e) if e.to_string().contains("zero sqrt_price_x96") => {
        tracing::debug!("pool unpriced (zero sqrt price)");
        Price::zero(FIXED_PRECISION)
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling decode_sqrt_price_x96_to_price_tokens_adjusted with invert=true, token0_decimals < token1_decimals, and sqrt_price_x96 = 0 (as via compute or spot_price).

Common situations: Subscribing to a freshly created Uniswap V3 pool before liquidity is added; a pool after all liquidity is removed; decoding on-chain slot0 data for an uninitialized pool.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/4a80693f0a715ec9. Report an issue: GitHub.