nautechsystems/nautilus_trader · error

Failed to parse '{field_name}' value '{value}' into Quantity

Error message

Failed to parse '{field_name}' value '{value}' into Quantity: {e}

What it means

Second failure point in `parse_quantity`: the string parsed into a `Decimal` but `Quantity::from_decimal_dp` rejected it after normalization and precision clamping. The decimal is valid but not representable as a Nautilus `Quantity` (magnitude or precision limits).

Source

Thrown at crates/adapters/dydx/src/common/parse.rs:145

}

/// Parses a decimal string into a [`Quantity`].
///
/// Normalizes the decimal to strip trailing zeros and clamps precision to
/// [`FIXED_PRECISION`] to prevent panics from venue values with excessive
/// decimal places.
///
/// # Errors
///
/// Returns an error if the string cannot be parsed into a valid quantity.
pub fn parse_quantity(value: &str, field_name: &str) -> anyhow::Result<Quantity> {
    let decimal = Decimal::from_str(value).map_err(|e| {
        anyhow::anyhow!("Failed to parse '{field_name}' value '{value}' into Decimal: {e}")
    })?;
    let normalized = decimal.normalize();
    let precision = (normalized.scale() as u8).min(FIXED_PRECISION);
    Quantity::from_decimal_dp(normalized, precision).map_err(|e| {
        anyhow::anyhow!("Failed to parse '{field_name}' value '{value}' into Quantity: {e}")
    })
}

/// Parses a decimal string into a [`Decimal`].
///
/// # Errors
///
/// Returns an error if the string cannot be parsed into a valid decimal.
pub fn parse_decimal(value: &str, field_name: &str) -> anyhow::Result<Decimal> {
    Decimal::from_str(value).map_err(|e| {
        anyhow::anyhow!("Failed to parse '{field_name}' value '{value}' into Decimal: {e}")
    })
}

/// Converts [`UnixNanos`] to seconds as `i64` using integer division.
///
/// Uses pure integer arithmetic to avoid floating-point precision loss that can
/// occur when converting large nanosecond timestamps (e.g., order expiry times).

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Convert raw token units to human units before parsing
  2. Clamp/round the size to the instrument's size increment and max quantity before parsing
  3. Inspect the wrapped `{e}` from Quantity::from_decimal_dp to see the exact constraint
  4. Validate sign and magnitude at the call site before parsing

Example fix

// before
let qty = parse_quantity("99999999999999999999", "size")?;
// after
let qty = parse_quantity(&size.min(max_qty).to_string(), "size")?;
Defensive patterns

Strategy: validation

Validate before calling

// Round to instrument size increment and cap before parsing
fn clamp_size(d: rust_decimal::Decimal, max: rust_decimal::Decimal) -> rust_decimal::Decimal {
    d.min(max)
}

Type guard

fn as_quantity(s: &str) -> Option<Quantity> { parse_quantity(s, "size").ok() }

Try / catch

let qty = parse_quantity(raw, "size").inspect_err(|e| log::error!("Quantity conversion failed: {e}"))?;

Prevention

When it happens

Trigger: Calling `parse_quantity` with extremely large quantities (e.g. wei-scale integers), negative values where invalid, or precision beyond Quantity's representable range even after clamping to FIXED_PRECISION.

Common situations: Sizes not converted from token raw units, copy-pasted values with excessive decimals, or programmatic sizes exceeding the exchange's representable range.

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