{"record":{"id":"54854e21015f60da","repo":"nautechsystems/nautilus_trader","slug":"missing-is-inverse-for","errorCode":null,"errorMessage":"Missing is_inverse for {}","messagePattern":"Missing is_inverse for (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/bitmex/src/websocket/messages.rs","lineNumber":600,"sourceCode":"            .ok_or_else(|| anyhow::anyhow!(\"Missing root_symbol for {}\", msg.symbol))?;\n        let underlying = msg\n            .underlying\n            .ok_or_else(|| anyhow::anyhow!(\"Missing underlying for {}\", msg.symbol))?;\n        let quote_currency = msg\n            .quote_currency\n            .ok_or_else(|| anyhow::anyhow!(\"Missing quote_currency for {}\", msg.symbol))?;\n        let tick_size = msg\n            .tick_size\n            .ok_or_else(|| anyhow::anyhow!(\"Missing tick_size for {}\", msg.symbol))?;\n        let multiplier = msg\n            .multiplier\n            .ok_or_else(|| anyhow::anyhow!(\"Missing multiplier for {}\", msg.symbol))?;\n        let is_quanto = msg\n            .is_quanto\n            .ok_or_else(|| anyhow::anyhow!(\"Missing is_quanto for {}\", msg.symbol))?;\n        let is_inverse = msg\n            .is_inverse\n            .ok_or_else(|| anyhow::anyhow!(\"Missing is_inverse for {}\", msg.symbol))?;\n\n        // Parse state - default to Open if not present\n        let state = msg\n            .state\n            .and_then(|s| serde_json::from_str::<BitmexInstrumentState>(&format!(\"\\\"{s}\\\"\")).ok())\n            .unwrap_or(BitmexInstrumentState::Open);\n\n        // Parse instrument type - default to PerpetualContract if not present\n        let instrument_type = msg\n            .instrument_type\n            .and_then(|t| serde_json::from_str::<BitmexInstrumentType>(&format!(\"\\\"{t}\\\"\")).ok())\n            .unwrap_or(BitmexInstrumentType::PerpetualContract);\n\n        Ok(Self {\n            symbol: msg.symbol,\n            root_symbol,\n            state,\n            instrument_type,","sourceCodeStart":582,"sourceCodeEnd":618,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/bitmex/src/websocket/messages.rs#L582-L618","documentation":"`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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify the raw payload contains `is_inverse`; if it does, check for serde field-name mismatches in the message struct.","Add the field to any hand-crafted fixture (e.g. `\"is_inverse\": true` for XBTUSD-style coin-margined contracts).","Update the adapter's message schema if BitMEX added/renamed the field.","Seed instrument state from BitMEX REST `/api/v1/instrument?symbol=...` which always returns `is_inverse`."],"exampleFix":"// before\nlet fixture = r#\"{\"symbol\":\"XBTUSD\",\"multiplier\":100000000,\"is_quanto\":false}\"#;\n// after\nlet fixture = r#\"{\"symbol\":\"XBTUSD\",\"multiplier\":100000000,\"is_quanto\":false,\"is_inverse\":true}\"#;","handlingStrategy":"validation","validationCode":"fn validate_instrument_msg(msg: &BitmexInstrumentMsg) -> Result<(), String> {\n    if msg.is_inverse.is_none() { return Err(format!(\"is_inverse missing for {}\", msg.symbol)); }\n    Ok(())\n}","typeGuard":"fn has_inverse(f: &Option<bool>) -> bool { f.is_some() }","tryCatchPattern":"match parse_instrument(msg) {\n    Ok(i) => i,\n    Err(e) if e.to_string().contains(\"Missing is_inverse\") => { log::warn!(\"skip: {e}\"); continue; }\n    Err(e) => return Err(e),\n}","preventionTips":["Verify all required instrument flags (multiplier, is_quanto, is_inverse) before processing updates.","Refresh instrument definitions via REST on websocket schema mismatch.","Version fixtures against the live API periodically."],"tags":["websocket","instrument","bitmex","missing-field"],"backgroundTag":"missing-required-argument","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}