nautechsystems/nautilus_trader · error
index is within the data batch
Error message
index is within the data batch
What it means
When (re)building the DataIterator heap, the code iterates each priority stream, reads the current per-priority index, and fetches data.get(idx) to seed the heap. The guard idx < data.len() runs immediately before the get, so expect("index is within the data batch") can only fail on an internal logic bug where the index map and stream contents disagree.
Source
Thrown at crates/backtest/src/data_iterator.rs:368
self.heap.is_empty()
}
}
fn rebuild_heap(&mut self) {
self.heap.clear();
// Determine if we're in single-stream mode
if self.streams.len() == 1 {
self.single_priority = self.streams.keys().next().copied();
return;
}
self.single_priority = None;
for (&priority, data) in &self.streams {
let idx = *self.indices.get(&priority).unwrap_or(&0);
if idx < data.len() {
self.heap.push(HeapEntry {
key: replay_key(data.get(idx).expect("index is within the data batch")),
priority,
index: idx,
});
}
}
}
}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use nautilus_model::{
data::{
Bar, FundingRateUpdate, IndexPriceUpdate, InstrumentClose, InstrumentStatus,
MarkPriceUpdate, OptionGreeks, OrderBookDelta, OrderBookDeltas, OrderBookDepth10,
QuoteTick, TradeTick,
stubs::{View on GitHub (pinned to 18893faf8b)
Solutions
- Do not mutate streams concurrently with heap construction
- Create a minimal reproduction and file a bug with the NautilusTrader project
- Upgrade to a version containing the fix if this is a known regression
Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure per-priority indices match stream lengths before building the iterator: assert!(streams.iter().all(|(p, d)| indices.get(p).map_or(true, |i| *i < d.len())));
Type guard
fn index_in_range(idx: usize, data: &[impl Sized]) -> bool { idx < data.len() } Try / catch
// Not catchable in normal Rust; isolate with a minimal backtest repro and file a bug.
Prevention
- Avoid concurrent mutation of streams/indices maps
- Construct DataIterator once and reuse rather than rebuilding mid-iteration
- Keep to supported public constructors
When it happens
Trigger: Only reachable if self.indices contains an index >= data.len() for a priority while the preceding if-check passes — i.e. a code defect or concurrent mutation of self.streams between the check and the get; not triggerable through normal public API use.
Common situations: Seen only with a corrupted or concurrently modified DataIterator, or a regression introduced by a code change. Not a user configuration issue.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Time event accumulator sequence overflow
- next index is within the data batch
- timer exists at timestamp
- Cannot handle command: {command:?}
- Latency model should be initialized
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/afbfdb497b586867.
Report an issue: GitHub.