nautechsystems/nautilus_trader · error

Failed to bootstrap instruments: {e}

Error message

Failed to bootstrap instruments: {e}

What it means

Raised in connect when the HTTP client fails to bootstrap instruments (fetch and parse the instrument definitions for the configured exchanges) from the Tardis API. Without instruments the client cannot map streams, so connect fails fast.

Source

Thrown at crates/adapters/tardis/src/data.rs:562

            self.config
                .stream_options
                .iter()
                .map(|opt| opt.exchange)
                .collect()
        } else {
            self.config.options.iter().map(|opt| opt.exchange).collect()
        };

        let base_url = resolve_ws_base_url(
            self.config
                .tardis_ws_url
                .as_ref()
                .map(|value| value.expose_secret()),
        )?;
        let (instrument_map, instruments) = http_client
            .bootstrap_instruments(&exchanges)
            .await
            .map_err(|e| anyhow::anyhow!("Failed to bootstrap instruments: {e}"))?;

        for instrument in instruments {
            if let Err(e) = self.data_sender.send(DataEvent::Instrument(instrument)) {
                log::error!("Failed to send instrument event: {e}");
            }
        }

        let url = self.build_ws_url(&base_url)?;

        let mode_label = if is_stream_mode { "stream" } else { "replay" };
        log::info!("Connecting to Tardis Machine {mode_label}");
        log::debug!("URL: {url}");

        let (ws_stream, _) = connect_async(&url)
            .await
            .map_err(|e| anyhow::anyhow!("Failed to connect to Tardis Machine: {e}"))?;

        log::info!("Connected to Tardis Machine");

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Verify the exchange names in the config match Tardis's exchange identifiers exactly.
  2. Check the API key is set and entitled for the requested exchanges/instruments.
  3. Test network connectivity to api.tardis.dev and check Tardis status/outages.
  4. Inspect `{e}` for HTTP status; back off and retry if rate-limited (429).

Example fix

// before
exchanges: vec!["binance-futures".into()],
// after: use the exact Tardis exchange id expected by the API
exchanges: vec!["binance-futures".into()], // confirm id at tardis.dev docs; e.g. not "binance_usd_m"
Defensive patterns

Strategy: retry

Validate before calling

// Validate config before connect
assert!(!config.exchanges.is_empty(), "exchanges must be set");
for ex in &config.exchanges {
    assert!(TARDIS_KNOWN_EXCHANGES.contains(&ex.as_str()), "unknown Tardis exchange: {ex}");
}

Try / catch

for attempt in 0..3 {
    match client.connect().await {
        Ok(()) => break,
        Err(e) if e.to_string().contains("Failed to bootstrap instruments") && attempt < 2 => {
            tokio::time::sleep(Duration::from_secs(2u64 << attempt)).await; // backoff
        }
        Err(e) => return Err(e),
    }
}

Prevention

When it happens

Trigger: bootstrap_instruments(&exchanges) returns Err: HTTP request failure, non-2xx response, unexpected payload, or unknown/misspelled exchange name in config.

Common situations: Wrong Tardis API key (missing entitlement), invalid exchange identifier in TardisDataClientConfig, network outage, Tardis API downtime or rate limiting.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/200c4b6a19184766. Report an issue: GitHub.