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

  1. Do not mutate streams concurrently with heap construction
  2. Create a minimal reproduction and file a bug with the NautilusTrader project
  3. 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

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


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