nautechsystems/nautilus_trader · error

Quantity overflow for ticks={ticks}, decimals={decimals}: {e

Error message

Quantity overflow for ticks={ticks}, decimals={decimals}: {e}

What it means

parse_quantity_from_ticks routes the tick count through rust_decimal's Decimal and Quantity::from_decimal_dp so that tick counts too large for Nautilus's fixed-precision Quantity representation return an error instead of panicking inside the unchecked mantissa-exponent constructor. This error means the numeric value implied by ticks=10^-decimals falls outside the Quantity range (roughly 18 significant digits).

Source

Thrown at crates/adapters/lighter/src/common/parse.rs:81

/// sign separately before invoking this parser.
///
/// Conversion routes through [`Decimal`] and [`Quantity::from_decimal_dp`]
/// so out-of-range tick counts return an error rather than panicking inside
/// the unchecked mantissa-exponent constructor.
///
/// # Errors
///
/// Returns an error if `decimals` exceeds [`MAX_DECIMALS`], if `ticks` is
/// negative, or if the resulting value exceeds the [`Quantity`] range.
pub fn parse_quantity_from_ticks(ticks: i64, decimals: u8) -> anyhow::Result<Quantity> {
    anyhow::ensure!(
        decimals <= MAX_DECIMALS,
        "size decimals {decimals} exceeds maximum {MAX_DECIMALS}",
    );
    anyhow::ensure!(ticks >= 0, "negative tick count {ticks} for Quantity");
    let decimal = Decimal::new(ticks, u32::from(decimals));
    Quantity::from_decimal_dp(decimal, decimals).map_err(|e| {
        anyhow::anyhow!("Quantity overflow for ticks={ticks}, decimals={decimals}: {e}")
    })
}

/// Converts a decimal string into a Nautilus [`Price`] at the requested precision.
///
/// # Errors
///
/// Returns an error if the string is not a decimal, if `precision` exceeds
/// [`MAX_DECIMALS`], or if the resulting value is out of range.
pub fn parse_price(value: &str, precision: u8) -> anyhow::Result<Price> {
    anyhow::ensure!(
        precision <= MAX_DECIMALS,
        "price precision {precision} exceeds maximum {MAX_DECIMALS}",
    );
    let decimal =
        Decimal::from_str(value).map_err(|e| anyhow::anyhow!("invalid price `{value}`: {e}"))?;
    Price::from_decimal_dp(decimal, precision)
        .map_err(|e| anyhow::anyhow!("invalid price `{value}` at precision {precision}: {e}"))

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the size_decimals value for the market against the orderBookDetails REST response — a wrong decimals value scales the value incorrectly.
  2. Sanity-check the raw tick count against plausible market maximums before conversion and reject out-of-band values upstream.
  3. Treat the message as a data-integrity problem: log ticks and decimals, drop the update, and flag the source payload rather than retrying.
  4. If you legitimately need larger values, you cannot — Nautilus Quantity is fixed-precision; the value must be capped or the payload rejected.

Example fix

// before
let qty = parse_quantity_from_ticks(ticks, decimals)?;
// after
if ticks > MAX_PLAUSIBLE_TICKS {
    return Err(anyhow::anyhow!("implausible tick count {ticks} for market"));
}
let qty = parse_quantity_from_ticks(ticks, decimals)?;
Defensive patterns

Strategy: validation

Validate before calling

const MAX_PLAUSIBLE_TICKS: i64 = 10_000_000_000_000_000;
fn ticks_in_range(ticks: i64) -> bool {
    (0..=MAX_PLAUSIBLE_TICKS).contains(&ticks)
}

Try / catch

match parse_quantity_from_ticks(ticks, decimals) {
    Ok(q) => q,
    Err(e) if e.to_string().contains("Quantity overflow") => {
        tracing::error!(%e, "implausible size; dropping update");
        return Ok(()); // skip malformed update
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling parse_quantity_from_ticks with a tick magnitude whose scaled value exceeds the Quantity fixed-point range — e.g. i64::MAX ticks, or large ticks combined with decimals that push the value past ~10^18.

Common situations: A malformed or hostile exchange payload with an absurd base_amount; a market whose size_decimals is misreported (far too small), inflating the implied value; unit tests probing the upper bound with i64::MAX.

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/380b5a5e59bc8cc5. Report an issue: GitHub.