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
- Inspect the embedded `{e}` for the API's specific complaint
- Validate that start <= end and the range overlaps the dataset's availability (see get_dataset_range)
- Confirm the symbols and inferred stype_in are valid for the dataset
- 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
- Validate time ranges (start < end, end within dataset availability) before the call
- Confirm symbols exist on the dataset via get_dataset_range/metadata first
- Handle rate limits with exponential backoff
- Keep the databento crate current to avoid schema/param mismatches
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
- Failed to get dataset range: {e}
- {e}
- Missing exchange in record: {e}
- Venue not found for exchange {exchange}: {e}
- Reconnection timeout after {timeout_mins} minutes: {e}
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/3fb79a6c69e6f75a.
Report an issue: GitHub.