nautechsystems/nautilus_trader · error

Liquidity {liquidity} exceeds i128::MAX

Error message

Liquidity {liquidity} exceeds i128::MAX

What it means

`PoolProfiler::add_liquidity` converts an unsigned on-chain liquidity amount (`u128`) into a signed `i128` delta for position tracking. `i128::try_from(liquidity)` fails when the liquidity exceeds `i128::MAX`, throwing this error. Values near u128::MAX are astronomically large in practice, so this almost always indicates corrupted or misparsed event data.

Source

Thrown at crates/model/src/defi/pool_analysis/profiler.rs:959

        Ok(())
    }

    /// Adds liquidity to a position.
    ///
    /// Updates position state, tracks deposited amounts, and manages tick maps.
    /// Called by both historical event processing and simulated operations.
    fn add_liquidity(
        &mut self,
        owner: &Address,
        tick_lower: i32,
        tick_upper: i32,
        liquidity: u128,
        amount0: U256,
        amount1: U256,
    ) -> anyhow::Result<()> {
        let liquidity_delta = i128::try_from(liquidity)
            .map_err(|_| anyhow::anyhow!("Liquidity {liquidity} exceeds i128::MAX"))?;
        self.update_position(
            owner,
            tick_lower,
            tick_upper,
            liquidity_delta,
            amount0,
            amount1,
        )?;

        // Track deposited amounts
        self.analytics.total_amount0_deposited += amount0;
        self.analytics.total_amount1_deposited += amount1;

        Ok(())
    }

    /// Executes a simulated mint (liquidity addition) operation.
    ///

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify your log/ABI decoding reads the correct word for `liquidity` in the mint event.
  2. Reject or clamp mints whose liquidity exceeds realistic maxima (Uniswap V3 caps liquidity well below i128::MAX) at ingestion.
  3. Skip the event with a logged warning instead of failing the whole profiling run.
  4. If you need to represent such magnitudes, widen your accounting type (not feasible with i128 position deltas — instead validate upstream).

Example fix

// before
profiler.add_liquidity(owner, tick_lower, tick_upper, liquidity, amount0, amount1)?;
// after
const MAX_SANE_LIQUIDITY: u128 = 1 << 120;
if liquidity > MAX_SANE_LIQUIDITY {
    eprintln!("implausible mint liquidity {liquidity}; skipping");
    return Ok(());
}
profiler.add_liquidity(owner, tick_lower, tick_upper, liquidity, amount0, amount1)?;
Defensive patterns

Strategy: validation

Validate before calling

fn liquidity_fits_i128(liquidity: u128) -> bool { liquidity <= i128::MAX as u128 }

Try / catch

match profiler.add_liquidity(owner, tl, tu, liq, a0, a1) {
    Ok(()) => {}
    Err(e) if e.to_string().contains("exceeds i128::MAX") => warn!("skipping corrupt mint: {e}"),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `add_liquidity` (via `process_mint`/`execute_mint`) with a `liquidity: u128` value greater than `i128::MAX` (≈1.7e38), typically from a misparsed mint event.

Common situations: ABI/log decoding bugs where unrelated bytes are read as liquidity; adversarial or fuzzed event data; reusing raw storage slots as liquidity values.

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