nautechsystems/nautilus_trader · error · anyhow::Error

Failed to get range: {e}

Error message

Failed to get range: {e}

What it means

Wraps a failure from the Databento Timeseries API `get_range` call used inside `get_range_instruments` to fetch instrument definitions. The databento error (auth, bad params, network, API status) is embedded in the message.

Source

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

        let stype_in = infer_symbology_type(first_symbol);
        let end = params.end.unwrap_or_else(|| self.clock.get_time_ns());
        let time_range = get_date_time_range(params.start, end)?;

        let range_params = GetRangeParams::builder()
            .dataset(params.dataset)
            .date_time_range(time_range)
            .symbols(symbols)
            .stype_in(stype_in)
            .schema(dbn::Schema::Definition)
            .maybe_limit(params.limit.and_then(NonZeroU64::new))
            .build();

        let mut client = (*self.inner).clone();
        let mut decoder = client
            .timeseries()
            .get_range(&range_params)
            .await
            .map_err(|e| anyhow::anyhow!("Failed to get range: {e}"))?;

        let metadata = decoder.metadata().clone();
        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()

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Inspect the embedded `{e}` for the API's specific complaint
  2. Validate that start <= end and the range overlaps the dataset's availability (see get_dataset_range)
  3. Confirm the symbols and inferred stype_in are valid for the dataset
  4. Check credentials and retry transient network/5xx failures

Example fix

// before
let end = params.end.unwrap_or_else(|| clock.get_time_ns());
// after
let end = params.end.unwrap_or_else(|| clock.get_time_ns());
assert!(end > params.start, "end must be after start");
Defensive patterns

Strategy: retry

Validate before calling

assert!(params.start < end, "start must precede end");
if params.dataset.is_empty() || params.symbols.is_empty() { bail!("invalid params"); }

Type guard

fn params_valid(start: u64, end: u64, dataset: &str, symbols: &[String]) -> bool {
    start < end && !dataset.is_empty() && !symbols.is_empty()
}

Try / catch

match client.get_range_instruments(params).await {
    Ok(i) => i,
    Err(e) if is_rate_limit(&e) => { sleep(backoff).await; retry(params).await }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling `get_range_instruments` where the timeseries request fails: invalid API key, bad dataset/symbol/symbology params, invalid start/end range, network error, or non-success API response.

Common situations: start after end, end in the future for a dataset not yet live, symbols not existing on the dataset, expired credentials, rate limits.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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