nautechsystems/nautilus_trader · error
Instrument {first_instrument_id} for the given data not foun
Error message
Instrument {first_instrument_id} for the given data not found in the cache. Add the instrument through `add_instrument()` prior to adding related data. What it means
Before running, the backtest engine registers all added data and requires that the instrument each data item refers to already exists in the cache. Data must be preceded by add_instrument() for its instrument id; otherwise register_added_data fails so the data cannot be priced or simulated without its instrument definition.
Source
Thrown at crates/backtest/src/engine.rs:477
) -> anyhow::Result<String> {
#[cfg(not(feature = "defi"))]
let _ = client_id;
let Some(first) = items.clone().next() else {
anyhow::bail!("data was empty");
};
if validate {
// Validate against the first element only and assume the batch is
// homogeneous (documented contract on add_data).
#[cfg(feature = "defi")]
let first_is_defi = matches!(first, DataRef::Defi(_));
#[cfg(not(feature = "defi"))]
let first_is_defi = false;
if !first_is_defi && !matches!(first, DataRef::Custom(_)) {
let first_instrument_id = first.instrument_id();
anyhow::ensure!(
self.kernel
.cache
.borrow()
.instrument(&first_instrument_id)
.is_some(),
"Instrument {first_instrument_id} for the given data not found in the cache. \
Add the instrument through `add_instrument()` prior to adding related data."
);
if let DataRef::Bar(bar) = first {
anyhow::ensure!(
bar.bar_type.aggregation_source() == AggregationSource::External,
"bar_type.aggregation_source must be External, was {:?}",
bar.bar_type.aggregation_source(),
);
}
}
}View on GitHub (pinned to 18893faf8b)
Solutions
- Call engine.add_instrument(...) for the instrument referenced by the data before add_data/add_data_batch.
- Verify the instrument_id in your data matches exactly (symbol and venue casing/format) the added instrument's id.
- If batch-loading, add all instruments first, then add data, then sort and run.
- For custom data (DataRef::Custom) or DeFi data, note these are exempt from the check — confirm you didn't accidentally wrap domain data as non-custom.
Example fix
// before engine.add_data(quote_ticks); engine.add_instrument(instrument); // after engine.add_instrument(instrument); engine.add_data(quote_ticks);
Defensive patterns
Strategy: validation
Validate before calling
// before adding data, ensure every referenced instrument is in the cache
for id in data_instrument_ids {
if engine.cache.instrument(&id).is_none() {
panic!("instrument {id} missing from cache; call add_instrument first");
}
} Prevention
- Always add all instruments before any data.
- Derive instrument ids from the data files and assert each resolves to a cached instrument.
- Watch for id format mismatches (symbol casing, venue suffix) between datasets and instruments.
When it happens
Trigger: Calling engine.add_data(...) or engine.add_data_batch(...) with quotes/trades/bars/deltas whose first item's instrument_id() is not in the cache — i.e. no matching add_instrument() call was made (or was made after adding data).
Common situations: Forgetting add_instrument when loading data-only backtests; instrument id mismatch between the data (e.g. 'EUR/USD.SIM') and the added instrument ('EUR/USD.IDEALPRO'); instruments added on a different engine instance.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- Lighter fill instrument {instrument_id} missing from cache
- Instrument {symbol} not found in cache
- Instrument {symbol} not found in cache, ensure instruments l
- Instrument {symbol} not in cache
- Data has been added but not sorted, call `engine.sort_data()
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/05284e535daef698.
Report an issue: GitHub.