{"record":{"id":"264b27eb40642281","repo":"nautechsystems/nautilus_trader","slug":"missing-exchange-in-record-e","errorCode":null,"errorMessage":"Missing exchange in record: {e}","messagePattern":"Missing exchange in record: (.+?)","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"crates/adapters/databento/src/historical.rs","lineNumber":320,"sourceCode":"\n        let metadata = decoder.metadata().clone();\n        let mut metadata_cache = MetadataCache::new(metadata);\n        let mut instruments = Vec::new();\n\n        while let Some(msg) = decoder.decode_record::<dbn::InstrumentDefMsg>().await? {\n            let record = dbn::RecordRef::from(msg);\n            let sym_map = self.symbol_venue_map.load();\n            let mut instrument_id = decode_nautilus_instrument_id(\n                &record,\n                &mut metadata_cache,\n                &self.publisher_venue_map,\n                &sym_map,\n            )?;\n\n            if self.use_exchange_as_venue && instrument_id.venue == Venue::GLBX() {\n                let exchange = msg\n                    .exchange()\n                    .map_err(|e| anyhow::anyhow!(\"Missing exchange in record: {e}\"))?;\n                let venue = Venue::from_code(exchange)\n                    .map_err(|e| anyhow::anyhow!(\"Venue not found for exchange {exchange}: {e}\"))?;\n                instrument_id.venue = venue;\n            }\n\n            match decode_instrument_def_msg(msg, instrument_id, None, None) {\n                Ok(Some(instrument)) => instruments.push(instrument),\n                Ok(None) => {} // Decoder logged a warning for the unsupported class\n                Err(e) => anyhow::bail!(\"Failed to decode instrument {instrument_id}: {e}\"),\n            }\n        }\n\n        for instrument in &instruments {\n            self.price_precisions\n                .insert(instrument.id().symbol, instrument.price_precision());\n        }\n\n        Ok(instruments)","sourceCodeStart":302,"sourceCodeEnd":338,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/databento/src/historical.rs#L302-L338","documentation":"When `use_exchange_as_venue` is enabled and the instrument's venue is GLBX, the adapter replaces the venue with the record's specific exchange code. If the raw DBN InstrumentDefMsg has no exchange field populated, `msg.exchange()` fails and this error wraps it. It indicates malformed/absent data in the record rather than an API call failure.","triggerScenarios":"Calling `get_range_instruments` with `use_exchange_as_venue = true` on a GLBX instrument definition record whose `exchange` field is empty/missing.","commonSituations":"Datasets or record versions where the exchange field is not populated; decoding non-Globex data that was tagged GLBX; changes in DBN schema between crate versions.","solutions":["Disable `use_exchange_as_venue` (pass false) so the default GLBX venue is kept","Check the dataset/record actually corresponds to CME Globex data with exchange codes","Update the databento/dbn crates to the latest version and refetch","Inspect the raw record to confirm the exchange field is genuinely empty"],"exampleFix":"// before\nlet client = DatabentoHistoricalClient::new(cred, path, clock, true)?; // use_exchange_as_venue = true\n// after\nlet client = DatabentoHistoricalClient::new(cred, path, clock, false)?;","handlingStrategy":"fallback","validationCode":"// if records may lack exchange codes, do not request per-exchange venues\nlet use_exchange_as_venue = false;","typeGuard":"fn msg_has_exchange(msg: &dbn::InstrumentDefMsg) -> bool { msg.exchange().is_ok() }","tryCatchPattern":"let venue = match msg.exchange() {\n    Ok(code) => Venue::from_code(code).unwrap_or(Venue::GLBX()),\n    Err(_) => Venue::GLBX(),\n};","preventionTips":["Enable use_exchange_as_venue only for datasets known to populate exchange fields","Inspect raw DBN records when migrating datasets or crate versions","Default to GLBX venue rather than hard-requiring the exchange field","Pin dbn crate versions and review changelogs for field changes"],"tags":["rust","databento","missing-field","instrument-definitions"],"backgroundTag":"unexpected-response-shape","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"}