nautechsystems/nautilus_trader · error

Invalid negative `contract_multiplier`: {value}

Error message

Invalid negative `contract_multiplier`: {value}

What it means

`decode_option_multiplier` rejects a negative `contract_multiplier` for OPRA Pillar options. The multiplier must be a positive i32 or a sentinel (0 or i32::MAX meaning derive from `unit_of_measure_qty`); any other negative value indicates corrupt or semantically invalid instrument definition data.

Source

Thrown at crates/adapters/databento/src/decode/instruments.rs:342

        .expiration_ns(expiration)
        .price_precision(price_increment.precision)
        .price_increment(price_increment)
        .multiplier(multiplier)
        .lot_size(lot_size)
        .ts_event(ts_event)
        .ts_init(ts_init)
        .build()?)
}

fn decode_option_multiplier(
    dataset: Option<dbn::Dataset>,
    contract_multiplier: i32,
    unit_of_measure_qty: i64,
) -> anyhow::Result<Quantity> {
    match (dataset, contract_multiplier) {
        (Some(dbn::Dataset::OpraPillar), 0 | i32::MAX) => decode_multiplier(unit_of_measure_qty),
        (Some(dbn::Dataset::OpraPillar), value) if value < 0 => {
            anyhow::bail!("Invalid negative `contract_multiplier`: {value}")
        }
        (Some(dbn::Dataset::OpraPillar), value) => {
            Ok(Quantity::from_mantissa_exponent(value as u64, 0, 0))
        }
        _ => decode_multiplier(unit_of_measure_qty),
    }
}

/// Decodes a Databento instrument definition message into an `OptionSpread` instrument.
///
/// # Errors
///
/// Returns an error if parsing or constructing `OptionSpread` fails.
pub fn decode_option_spread(
    msg: &dbn::InstrumentDefMsg,
    instrument_id: InstrumentId,
    ts_init: Option<UnixNanos>,
    decode_config: Option<&DatabentoDecodeConfig>,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the instrument definition record and fix the source data multiplier
  2. Use 0 or i32::MAX to trigger derivation from `unit_of_measure_qty` instead of a negative value
  3. Add pre-validation of multiplier values before decoding
  4. Report the record to Databento support if it appears to be bad upstream data

Example fix

// before
contract_multiplier: -100
// after
contract_multiplier: 100 // or 0 / i32::MAX to derive from unit_of_measure_qty
Defensive patterns

Strategy: validation

Validate before calling

fn validate_multiplier(m: i32) -> Result<(), String> {
    if m < 0 && m != i32::MAX { Err(format!("contract_multiplier must be >=0 or i32::MAX, got {m}")) } else { Ok(()) }
}

Try / catch

match decode_option_contract(def) {
    Ok(inst) => inst,
    Err(e) if e.to_string().contains("Invalid negative `contract_multiplier`") => { /* skip or correct the record */ }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Decoding a Databento option instrument definition (via `decode_option_contract`) where the OPRA dataset record carries `contract_multiplier < 0` and it is not the 0 or i32::MAX sentinel.

Common situations: Corrupted or anomalous Databento instrument definition records; upstream schema changes introducing negative multipliers; feeding synthetic/test data with negative 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/ed32d5f666c7c908. Report an issue: GitHub.