nautechsystems/nautilus_trader · error

Invalid negative multiplier: {v}

Error message

Invalid negative multiplier: {v}

What it means

`decode_multiplier` converts an i64 multiplier (scaled by 1e9) into a `Quantity`, mapping 0 and `i64::MAX` to a default quantity of 1. Negative values are invalid for a contract multiplier and cause this error. It guards instrument definition decoding against nonsensical negative multiplier data.

Source

Thrown at crates/adapters/databento/src/decode/primitives.rs:372

    if value == dbn::UNDEF_TIMESTAMP {
        None
    } else {
        Some(UnixNanos::from(value))
    }
}

/// Decodes a multiplier from the given value, expressed in units of 1e-9.
/// Uses exact integer arithmetic to avoid precision loss in financial calculations.
///
/// # Errors
///
/// Returns an error if value is negative (invalid multiplier).
pub fn decode_multiplier(value: i64) -> anyhow::Result<Quantity> {
    const SCALE: u64 = 1_000_000_000;

    match value {
        0 | i64::MAX => Ok(quantity_from_whole(1)),
        v if v < 0 => anyhow::bail!("Invalid negative multiplier: {v}"),
        v => {
            let mantissa = v as u64;
            let mut frac_part = mantissa % SCALE;
            let mut precision = 9u8;
            while precision > 0 && frac_part.is_multiple_of(10) {
                frac_part /= 10;
                precision -= 1;
            }

            Ok(Quantity::from_mantissa_exponent_checked(
                mantissa, -9, precision,
            )?)
        }
    }
}

/// Decodes a lot size from the given value, expressed in standard whole-number units.
///

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the raw definition record's multiplier field and confirm whether the negative value is a data error on the vendor side.
  2. Exclude instruments with negative multipliers before decoding (pre-filter the definitions response).
  3. If 0/i64::MAX-style defaults are what you expect for this asset class, normalize the value before calling (clamp to 0/UNDEF).
  4. Catch the anyhow error at the instrument-decoding site and skip the instrument with a log.

Example fix

// before
let mult = decode_multiplier(def.multiplier as i64)?;
// after
let raw = def.multiplier as i64;
let mult = if raw < 0 { quantity_from_whole(1) } else { decode_multiplier(raw)? };
Defensive patterns

Strategy: validation

Validate before calling

fn multiplier_valid(raw: i64) -> bool { raw >= 0 } // 0 and i64::MAX default to 1

Type guard

fn is_negative_multiplier(v: i64) -> bool { v < 0 }

Try / catch

match decode_multiplier(raw) {
    Ok(q) => q,
    Err(e) => { log::warn!("bad multiplier: {e}"); quantity_from_whole(1) }
}

Prevention

When it happens

Trigger: `decode_multiplier(v)` called with `v < 0`, via `decode_currency_pair`, `decode_futures_contract`, `decode_futures_spread`, `decode_option_multiplier`, or `decode_option_spread` when a definition record's multiplier field is negative.

Common situations: Corrupt or unusual Databento definition records (negative multiplier), double-sign encoding mistakes in upstream data, or wrong schema/asset class being fed to the decoder.

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