nautechsystems/nautilus_trader · error

Missing multiplier for {}

Error message

Missing multiplier for {}

What it means

BitMEX instrument definition messages must carry the contract `multiplier` field to convert raw price/size values into instrument-native units. The adapter refuses to build an instrument spec when the websocket `instrument` message omits it, returning this anyhow error. It guards against silently producing instruments with wrong value calculations.

Source

Thrown at crates/adapters/bitmex/src/websocket/messages.rs:594

    fn try_from(msg: BitmexInstrumentMsg) -> Result<Self, Self::Error> {
        use crate::common::enums::{BitmexInstrumentState, BitmexInstrumentType};

        // Required fields
        let root_symbol = msg
            .root_symbol
            .ok_or_else(|| anyhow::anyhow!("Missing root_symbol for {}", msg.symbol))?;
        let underlying = msg
            .underlying
            .ok_or_else(|| anyhow::anyhow!("Missing underlying for {}", msg.symbol))?;
        let quote_currency = msg
            .quote_currency
            .ok_or_else(|| anyhow::anyhow!("Missing quote_currency for {}", msg.symbol))?;
        let tick_size = msg
            .tick_size
            .ok_or_else(|| anyhow::anyhow!("Missing tick_size for {}", msg.symbol))?;
        let multiplier = msg
            .multiplier
            .ok_or_else(|| anyhow::anyhow!("Missing multiplier for {}", msg.symbol))?;
        let is_quanto = msg
            .is_quanto
            .ok_or_else(|| anyhow::anyhow!("Missing is_quanto for {}", msg.symbol))?;
        let is_inverse = msg
            .is_inverse
            .ok_or_else(|| anyhow::anyhow!("Missing is_inverse for {}", msg.symbol))?;

        // Parse state - default to Open if not present
        let state = msg
            .state
            .and_then(|s| serde_json::from_str::<BitmexInstrumentState>(&format!("\"{s}\"")).ok())
            .unwrap_or(BitmexInstrumentState::Open);

        // Parse instrument type - default to PerpetualContract if not present
        let instrument_type = msg
            .instrument_type
            .and_then(|t| serde_json::from_str::<BitmexInstrumentType>(&format!("\"{t}\"")).ok())
            .unwrap_or(BitmexInstrumentType::PerpetualContract);

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Check the raw BitMEX `instrument` message payload and confirm the `multiplier` field is present for the symbol.
  2. Update the message struct/fixture to deserialize `multiplier` (add it to test JSON if a fixture is missing it).
  3. If BitMEX no longer sends `multiplier` for a new instrument type, use a documented default explicitly rather than hiding it.
  4. Re-fetch the instrument definition via BitMEX REST `/api/v1/instrument` which always includes `multiplier`.

Example fix

// before
let msg = serde_json::from_str::<BitmexInstrumentMsg>(r#"{"symbol":"XBTUSD"}"#)?;
// after
let msg = serde_json::from_str::<BitmexInstrumentMsg>(r#"{"symbol":"XBTUSD","multiplier":100000000}"#)?;
Defensive patterns

Strategy: validation

Validate before calling

fn validate_instrument_msg(msg: &BitmexInstrumentMsg) -> Result<(), String> {
    if msg.multiplier.is_none() { return Err(format!("multiplier missing for {}", msg.symbol)); }
    Ok(())
}

Type guard

fn has_multiplier(m: &Option<i64>) -> bool { m.is_some() }

Try / catch

match parse_instrument(msg) {
    Ok(instr) => instr,
    Err(e) if e.to_string().contains("Missing multiplier") => { log::warn!("skipping instrument: {e}"); continue; }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: A BitMEX websocket `instrument` message for a symbol arrives (or is constructed in tests) with `multiplier` absent or null, and the instrument-parsing code at crates/adapters/bitmex/src/websocket/messages.rs:594 calls `msg.multiplier.ok_or_else(...)`.

Common situations: BitMEX changes or trims the instrument payload; a custom/test message fixture omits `multiplier`; an upstream deserializer skips missing fields instead of erroring, so the None propagates to this check.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/ae305fe3562a5910. Report an issue: GitHub.