nautechsystems/nautilus_trader · error

Missing is_inverse for {}

Error message

Missing is_inverse for {}

What it means

`is_inverse` distinguishes inverse (coin-margined) from linear BitMEX contracts and is required to compute position sizes and PnL correctly. The adapter raises this error when the instrument message arrives without the flag rather than defaulting it, since an inverse/linear mix-up produces incorrect value semantics.

Source

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

            .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);

        Ok(Self {
            symbol: msg.symbol,
            root_symbol,
            state,
            instrument_type,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the raw payload contains `is_inverse`; if it does, check for serde field-name mismatches in the message struct.
  2. Add the field to any hand-crafted fixture (e.g. `"is_inverse": true` for XBTUSD-style coin-margined contracts).
  3. Update the adapter's message schema if BitMEX added/renamed the field.
  4. Seed instrument state from BitMEX REST `/api/v1/instrument?symbol=...` which always returns `is_inverse`.

Example fix

// before
let fixture = r#"{"symbol":"XBTUSD","multiplier":100000000,"is_quanto":false}"#;
// after
let fixture = r#"{"symbol":"XBTUSD","multiplier":100000000,"is_quanto":false,"is_inverse":true}"#;
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

fn has_inverse(f: &Option<bool>) -> bool { f.is_some() }

Try / catch

match parse_instrument(msg) {
    Ok(i) => i,
    Err(e) if e.to_string().contains("Missing is_inverse") => { log::warn!("skip: {e}"); continue; }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Instrument parsing reaches `msg.is_inverse.ok_or_else(...)` at crates/adapters/bitmex/src/websocket/messages.rs:600 with `is_inverse` null/absent in the BitMEX `instrument` message for the symbol.

Common situations: Test message fixtures built by hand omitting `is_inverse`; intermediate middleware or proxies trimming fields; newly listed instrument types where the client library's schema is out of date.

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