nautechsystems/nautilus_trader · error · anyhow::Error

Invalid {field_name} value

Error message

Invalid {field_name} value

What it means

convert_contract_quantity converts an optional raw numeric field (e.g. contract-specific min/max quantity) into a Quantity by multiplying with the contract decimal. It fails when the raw value string cannot be parsed into a Decimal, i.e. the exchange sent a non-finite or otherwise unparsable number for the named field.

Source

Thrown at crates/adapters/bitmex/src/common/parse.rs:191

    Ok((contract_decimal, size_increment))
}

/// Converts an optional contract-count field (e.g. `lotSize`, `maxOrderQty`) into a Nautilus
/// quantity using the previously derived contract size.
///
/// # Errors
///
/// Returns an error when the raw value cannot be represented with the available precision.
pub fn convert_contract_quantity(
    value: Option<f64>,
    contract_decimal: Decimal,
    max_scale: u32,
    field_name: &str,
) -> anyhow::Result<Option<Quantity>> {
    value
        .map(|raw| {
            let mut decimal = Decimal::from_str(&raw.to_string())
                .map_err(|_| anyhow::anyhow!("Invalid {field_name} value"))?
                * contract_decimal;
            let scale = decimal.scale();
            if scale > max_scale {
                decimal = decimal
                    .round_dp_with_strategy(max_scale, RoundingStrategy::MidpointAwayFromZero);
            }
            let decimal = decimal.normalize();
            let precision = decimal.scale() as u8;
            Quantity::from_decimal_dp(decimal, precision).map_err(anyhow::Error::from)
        })
        .transpose()
}

/// Converts a signed BitMEX contracts value into a Nautilus quantity using instrument precision.
#[must_use]
pub fn parse_signed_contracts_quantity(value: i64, instrument: &InstrumentAny) -> Quantity {
    let abs_value = value.checked_abs().unwrap_or_else(|| {
        log::warn!("Quantity value {value} overflowed when taking absolute value");

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Look at field_name in the message to identify which quantity field is malformed and inspect the raw instrument payload
  2. Fix or filter the instrument definition before re-running the adapter
  3. Validate the raw f64 is finite before calling convert_contract_quantity

Example fix

// before
convert_contract_quantity(Some(raw_min_qty), ...)
// after
if raw_min_qty.is_finite() {
    convert_contract_quantity(Some(raw_min_qty), ...)
} else {
    anyhow::bail!("non-finite {} for {}", field_name, symbol);
}
Defensive patterns

Strategy: validation

Validate before calling

fn valid_quantity_field(raw: f64) -> bool { raw.is_finite() && raw > 0.0 }

Type guard

fn finite_f64(x: f64) -> bool { x.is_finite() }

Try / catch

match convert_contract_quantity(value, cd, max_scale, field_name) {
    Ok(q) => q,
    Err(e) if e.to_string().contains(field_name) => {
        log::warn!("bad {} from exchange, skipping instrument", field_name);
        return Err(e);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Parsing a spot/perpetual/futures instrument whose minQty/maxQty/lotSize-style field (identified by field_name) is NaN, infinite, or not Decimal-representable.

Common situations: Unexpected instrument metadata from BitMEX (null coerced oddly, float inf), or test fixtures with placeholder values.

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