{"record":{"id":"3dfacd3a2d3bcb27","repo":"nautechsystems/nautilus_trader","slug":"missing-is-quanto-for","errorCode":null,"errorMessage":"Missing is_quanto for {}","messagePattern":"Missing is_quanto for (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/bitmex/src/websocket/messages.rs","lineNumber":597,"sourceCode":"        // 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);\n\n        Ok(Self {\n            symbol: msg.symbol,","sourceCodeStart":579,"sourceCodeEnd":615,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/bitmex/src/websocket/messages.rs#L579-L615","documentation":"The `is_quanto` flag tells the adapter whether a BitMEX contract is quanto-settled, which affects currency conversion of PnL/fees. When the instrument message lacks this field the adapter fails fast with this error instead of guessing settlement semantics. Wrong or missing quanto flags would corrupt money calculations.","triggerScenarios":"Parsing a BitMEX `instrument` websocket update where `msg.is_quanto` is None at crates/adapters/bitmex/src/websocket/messages.rs:597 — i.e. the payload omitted the `is_quanto` key or it deserialized to null.","commonSituations":"Partial instrument snapshots from custom relays; hand-written test JSON fixtures missing the flag; BitMEX API payload changes; a mapper that drops fields it does not recognize before the adapter sees them.","solutions":["Inspect the received instrument payload and ensure `is_quanto` is included (it is always present in BitMEX instrument records).","Fix the deserialization path so the field is not stripped (check serde field renames/skip rules).","Update any local test fixtures to include `\"is_quanto\": false` (or true as appropriate).","Pull a full instrument definition from BitMEX REST to populate all required fields before processing."],"exampleFix":"// before\nlet payload = r#\"{\"symbol\":\"ETHUSD\",\"multiplier\":1000000000000}\"#;\n// after\nlet payload = r#\"{\"symbol\":\"ETHUSD\",\"multiplier\":1000000000000,\"is_quanto\":false}\"#;","handlingStrategy":"validation","validationCode":"fn validate_instrument_msg(msg: &BitmexInstrumentMsg) -> Result<(), String> {\n    if msg.is_quanto.is_none() { return Err(format!(\"is_quanto missing for {}\", msg.symbol)); }\n    Ok(())\n}","typeGuard":"fn has_quanto(f: &Option<bool>) -> bool { f.is_some() }","tryCatchPattern":"if let Err(e) = parse_instrument(msg) {\n    if e.to_string().contains(\"Missing is_quanto\") { log::warn!(\"skip: {e}\"); } else { return Err(e); }\n}","preventionTips":["Never strip fields in intermediate mappers; deserialize the full payload into the adapter type.","Use real BitMEX captures for fixtures.","Monitor upstream API changelogs for payload changes."],"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"}