nautechsystems/nautilus_trader · error · anyhow::Error

Venue not found for exchange {exchange}: {e}

Error message

Venue not found for exchange {exchange}: {e}

What it means

After reading the exchange code from a GLBX instrument definition record (with `use_exchange_as_venue = true`), the adapter maps it to a Nautilus `Venue` via `Venue::from_code`. If no venue is registered for that exchange code, this error reports the unknown code and the underlying lookup error.

Source

Thrown at crates/adapters/databento/src/historical.rs:322

        let mut metadata_cache = MetadataCache::new(metadata);
        let mut instruments = Vec::new();

        while let Some(msg) = decoder.decode_record::<dbn::InstrumentDefMsg>().await? {
            let record = dbn::RecordRef::from(msg);
            let sym_map = self.symbol_venue_map.load();
            let mut instrument_id = decode_nautilus_instrument_id(
                &record,
                &mut metadata_cache,
                &self.publisher_venue_map,
                &sym_map,
            )?;

            if self.use_exchange_as_venue && instrument_id.venue == Venue::GLBX() {
                let exchange = msg
                    .exchange()
                    .map_err(|e| anyhow::anyhow!("Missing exchange in record: {e}"))?;
                let venue = Venue::from_code(exchange)
                    .map_err(|e| anyhow::anyhow!("Venue not found for exchange {exchange}: {e}"))?;
                instrument_id.venue = venue;
            }

            match decode_instrument_def_msg(msg, instrument_id, None, None) {
                Ok(Some(instrument)) => instruments.push(instrument),
                Ok(None) => {} // Decoder logged a warning for the unsupported class
                Err(e) => anyhow::bail!("Failed to decode instrument {instrument_id}: {e}"),
            }
        }

        for instrument in &instruments {
            self.price_precisions
                .insert(instrument.id().symbol, instrument.price_precision());
        }

        Ok(instruments)
    }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Update nautilus_trader (and its exchange-code mappings) to a version that includes the venue
  2. Disable `use_exchange_as_venue` so records keep the generic GLBX venue instead of per-exchange venues
  3. Register/add the venue mapping for the specific exchange code if extending the adapter
  4. Log the failing exchange code and check Databento docs for its canonical code

Example fix

// before
let client = DatabentoHistoricalClient::new(cred, path, clock, true)?;
// after
// keep use_exchange_as_venue only if all exchange codes are mapped in your nautilus version
let client = DatabentoHistoricalClient::new(cred, path, clock, false)?;
Defensive patterns

Strategy: try-catch

Validate before calling

// check mapping coverage before enabling per-exchange venues
let use_exchange_as_venue = all_exchanges_known_to_nautilus();

Type guard

fn venue_exists(code: &str) -> bool { Venue::from_code(code).is_ok() }

Try / catch

let venue = Venue::from_code(exchange)
    .map_err(|e| { log::warn!("unknown exchange {exchange}: {e}; falling back to GLBX"); Venue::GLBX() });

Prevention

When it happens

Trigger: `get_range_instruments` encounters a record whose exchange code has no corresponding Nautilus Venue mapping (e.g. a new or unsupported exchange code, or a lowercase/unexpected code string).

Common situations: New CME exchanges not yet mapped in the installed nautilus version; custom/fictional exchanges in test data; dataset mixing exchanges outside the GLBX mappings.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — 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/359db0f9d36209a9. Report an issue: GitHub.