nautechsystems/nautilus_trader · error

Invalid levels: {}

Error message

Invalid levels: {}

What it means

Depth10StreamIterator::next returns this error when self.levels holds a value other than 5 or 25 inside the iterator loop. In normal use Depth10StreamIterator::new already guarantees levels is 5 or 25 via anyhow::ensure!, so reaching this arm indicates the iterator was constructed directly (bypassing new) or an internal invariant was broken.

Source

Thrown at crates/adapters/tardis/src/csv/stream.rs:1528

            return Some(Ok(chunk));
        }

        self.buffer.clear();
        let mut records_read = 0;

        while records_read < self.chunk_size {
            match self.reader.read_record(&mut self.record) {
                Ok(true) => {
                    let result = match self.levels {
                        5 => self
                            .record
                            .deserialize::<TardisOrderBookSnapshot5Record>(None)
                            .map(|data| self.process_snapshot5(&data)),
                        25 => self
                            .record
                            .deserialize::<TardisOrderBookSnapshot25Record>(None)
                            .map(|data| self.process_snapshot25(&data)),
                        _ => return Some(Err(anyhow::anyhow!("Invalid levels: {}", self.levels))),
                    };

                    match result {
                        Ok(depth) => {
                            self.buffer.push(depth);
                            records_read += 1;
                            self.records_processed += 1;

                            if let Some(limit) = self.limit
                                && self.records_processed >= limit
                            {
                                break;
                            }
                        }
                        Err(e) => {
                            return Some(Err(anyhow::anyhow!("Failed to deserialize record: {e}")));
                        }
                    }

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Always construct the iterator via Depth10StreamIterator::new (or the public stream_order_book_depth10) which validates levels.
  2. If you instantiate directly, ensure levels == 5 || levels == 25 before use.
  3. Do not mutate levels after construction; it is a fixed stream property.
  4. If you hit this in library code, file a bug — it signals an internal invariant violation.

Example fix

// before: direct struct construction bypassing validation
let it = Depth10StreamIterator { levels: 10, .. };
// after: go through new(), which ensures levels is 5 or 25
let it = Depth10StreamIterator::new(path, chunk, 10, None, None, None, None)?;
// -> returns "Invalid levels: 10. Must be 5 or 25." early, before streaming
Defensive patterns

Strategy: type-guard

Validate before calling

// library users never reach this arm; guard construction path instead
let levels = if file_is_snapshot25 { 25 } else { 5 };
anymore::ensure!(levels == 5 || levels == 25);

Type guard

fn is_supported_levels(levels: u8) -> bool { levels == 5 || levels == 25 }

Try / catch

// the iterator only errors here if built without new(); always use:
let it = stream_order_book_depth10(path, chunk, levels, None, None, None, None)?;
// which validates levels up front

Prevention

When it happens

Trigger: Constructing Depth10StreamIterator with a struct literal instead of new() and a levels field outside {5, 25}; any code path that mutates levels after construction; the match's fall-through arm at line 1528.

Common situations: Internal maintenance or test code instantiating the private iterator directly; refactoring that moved or removed the constructor check.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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