nautechsystems/nautilus_trader · error
next index is within the data batch
Error message
next index is within the data batch
What it means
During heap replay in the backtest DataIterator, an entry's cursor is advanced to next_index and the corresponding item is fetched from the stream batch before being pushed back onto the heap. The code asserts with expect() that next_index is in bounds because the caller only advances when next_index < stream.len(). Violation indicates an internal cursor/heap bookkeeping bug, not bad user input.
Source
Thrown at crates/backtest/src/data_iterator.rs:309
// Multi-stream path using heap
let Some(entry) = self.heap.pop() else {
return;
};
let Some(stream) = self.streams.get(&entry.priority) else {
return;
};
// Advance cursor and push next entry
let next_index = entry.index + 1;
self.indices.insert(entry.priority, next_index);
if next_index < stream.len() {
self.heap.push(HeapEntry {
key: replay_key(
stream
.get(next_index)
.expect("next index is within the data batch"),
),
priority: entry.priority,
index: next_index,
});
}
}
/// Returns the next backtest data element across all streams in replay order.
pub(crate) fn next_item(&mut self) -> Option<Data> {
let element = if let Some(p) = self.single_priority {
let data = self.streams.get(&p)?;
let idx = *self.indices.get(&p)?;
data.get_owned(idx)?
} else {
let entry = self.heap.peek()?;
self.streams.get(&entry.priority)?.get_owned(entry.index)?
};
View on GitHub (pinned to 18893faf8b)
Solutions
- Verify no custom code mutates the underlying data batch while iterating
- Reproduce with a minimal dataset and report the bug to NautilusTrader maintainers with the repro
- Pin/upgrade to a version where the data_iterator heap bug is fixed
Defensive patterns
Strategy: type-guard
Validate before calling
// Guard custom data batches passed to the backtest iterator: assert!(stream.iter().all(|d| !is_stale(d)), "stream contains stale entries");
Type guard
fn in_bounds(idx: usize, stream_len: usize) -> bool { idx < stream_len } Try / catch
// Panic is not catchable in normal Rust; verify with a custom Clock/TestClock harness // and report a repro to maintainers if hit.
Prevention
- Do not mutate data batches while the backtest iterator is running
- Use the standard DataEngine/data loading paths rather than custom stream injection
- Test custom streams against a small fixed dataset before long runs
When it happens
Trigger: Only reachable via a defect in DataIterator's heap replay logic where an entry is re-pushed with next_index >= stream.len() (stale index, double-advance, or mutated stream). Normal API use (iterating the backtest data stream) cannot trigger it.
Common situations: Encountered only after upgrading NautilusTrader versions where iterator internals changed, or when a custom data stream implementation mutates during iteration. End users should never see this.
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
- 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/c40669ea719ec373.
Report an issue: GitHub.