nautechsystems/nautilus_trader · error

raw wei value exceeds 128-bit range

Error message

raw wei value exceeds 128-bit range

What it means

Price::from_wei converts a raw wei U256 into the crate's 128-bit fixed-precision internal representation via try_into().expect(...). Any wei value larger than u128::MAX panics with this message, and values above i128::MAX are rejected by the following assert. It exists because Price cannot represent arbitrarily large 256-bit values losslessly.

Source

Thrown at crates/model/src/defi/types/price.rs:39

impl Price {
    /// Constructs a [`Price`] from a raw amount expressed in wei (18-decimal fixed-point).
    ///
    /// The resulting [`Price`] will always have `precision` equal to `18`.
    ///
    /// # Panics
    ///
    /// Panics if the supplied `raw_wei` cannot fit into a signed 128-bit integer (this would
    /// exceed the numeric range of the internal `PriceRaw` representation).
    #[must_use]
    pub fn from_wei<U>(raw_wei: U) -> Self
    where
        U: Into<U256>,
    {
        let raw_u256: U256 = raw_wei.into();
        let raw_u128: u128 = raw_u256
            .try_into()
            .expect("raw wei value exceeds 128-bit range");

        assert!(
            raw_u128 <= i128::MAX as u128,
            "raw wei value exceeds signed 128-bit range"
        );

        let raw_i128: i128 = raw_u128 as i128;
        Self::from_raw(raw_i128, 18)
    }

    /// Converts this [`Price`] to a wei amount (U256).
    ///
    /// Only valid for prices with precision 18. For other precisions convert to precision 18 first.
    ///
    /// # Panics
    ///
    /// Panics if the price has precision other than 18 or if the raw value is negative.
    #[must_use]

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Guard before calling: ensure raw_wei <= U256::from(i128::MAX) before from_wei; otherwise reject the tick/update.
  2. Re-check the scaling math that produced the raw wei (off-by-10^decimals scaling is the usual culprit).
  3. Sanity-clamp incoming prices to a plausible band for the instrument before conversion.
  4. If real prices can exceed 128 bits, use a string/decimal representation rather than from_wei.

Example fix

// before
let price = Price::from_wei(raw_wei, 18); // panics on overflow
// after
assert!(raw_wei <= U256::from(i128::MAX), "price wei out of range");
let price = Price::from_wei(raw_wei, 18);
Defensive patterns

Strategy: validation

Validate before calling

fn price_wei_in_range(raw_wei: U256) -> bool {
    raw_wei <= U256::from(i128::MAX)
}

Type guard

fn to_price_raw(raw: U256) -> Option<u128> {
    let r: u128 = raw.try_into().ok()?;
    (r <= i128::MAX as u128).then_some(r)
}

Prevention

When it happens

Trigger: Calling Price::from_wei with raw_wei > u128::MAX — e.g. a price quoted in a token with extreme decimals, a garbage/oracle-corrupted value, or a wrongly scaled raw amount (multiplying instead of keeping raw units).

Common situations: Ingesting mis-scaled prices from a DEX event (raw units double-scaled), bad oracle feeds, or decoding dust/uint256 fields from contracts where the value is not actually a price.

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/9ae1129f525e72f3. Report an issue: GitHub.