{"record":{"id":"ae305fe3562a5910","repo":"nautechsystems/nautilus_trader","slug":"missing-multiplier-for","errorCode":null,"errorMessage":"Missing multiplier for {}","messagePattern":"Missing multiplier for (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/bitmex/src/websocket/messages.rs","lineNumber":594,"sourceCode":"    fn try_from(msg: BitmexInstrumentMsg) -> Result<Self, Self::Error> {\n        use crate::common::enums::{BitmexInstrumentState, BitmexInstrumentType};\n\n        // Required fields\n        let root_symbol = msg\n            .root_symbol\n            .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);","sourceCodeStart":576,"sourceCodeEnd":612,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/bitmex/src/websocket/messages.rs#L576-L612","documentation":"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.","triggerScenarios":"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(...)`.","commonSituations":"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.","solutions":["Check the raw BitMEX `instrument` message payload and confirm the `multiplier` field is present for the symbol.","Update the message struct/fixture to deserialize `multiplier` (add it to test JSON if a fixture is missing it).","If BitMEX no longer sends `multiplier` for a new instrument type, use a documented default explicitly rather than hiding it.","Re-fetch the instrument definition via BitMEX REST `/api/v1/instrument` which always includes `multiplier`."],"exampleFix":"// before\nlet msg = serde_json::from_str::<BitmexInstrumentMsg>(r#\"{\"symbol\":\"XBTUSD\"}\"#)?;\n// after\nlet msg = serde_json::from_str::<BitmexInstrumentMsg>(r#\"{\"symbol\":\"XBTUSD\",\"multiplier\":100000000}\"#)?;","handlingStrategy":"validation","validationCode":"fn validate_instrument_msg(msg: &BitmexInstrumentMsg) -> Result<(), String> {\n    if msg.multiplier.is_none() { return Err(format!(\"multiplier missing for {}\", msg.symbol)); }\n    Ok(())\n}","typeGuard":"fn has_multiplier(m: &Option<i64>) -> bool { m.is_some() }","tryCatchPattern":"match parse_instrument(msg) {\n    Ok(instr) => instr,\n    Err(e) if e.to_string().contains(\"Missing multiplier\") => { log::warn!(\"skipping instrument: {e}\"); continue; }\n    Err(e) => return Err(e),\n}","preventionTips":["Seed instruments from BitMEX REST /api/v1/instrument, which always includes multiplier.","Keep test fixtures synchronized with real captured payloads.","Alert on instrument-parse failures so schema drift is caught early."],"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-14T00:17:10.932Z"}