nautechsystems/nautilus_trader · error

Invalid levels: {levels}. Must be 5 or 25.

Error message

Invalid levels: {levels}. Must be 5 or 25.

What it means

Depth10StreamIterator::new validates the levels parameter with anyhow::ensure! and returns this error when levels is neither 5 nor 25. The Tardis CSV order-book snapshot data only comes in depth-5 (snapshot5) and depth-25 (snapshot25) record variants, so any other depth is rejected at construction time.

Source

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

    records_processed: usize,
}

impl Depth10StreamIterator {
    /// Creates a new [`Depth10StreamIterator`].
    ///
    /// # Errors
    ///
    /// Returns an error if the file cannot be opened or read, or if `levels` is not 5 or 25.
    pub(crate) fn new<P: AsRef<Path>>(
        filepath: P,
        chunk_size: usize,
        levels: u8,
        price_precision: Option<u8>,
        size_precision: Option<u8>,
        instrument_id: Option<InstrumentId>,
        limit: Option<usize>,
    ) -> anyhow::Result<Self> {
        anyhow::ensure!(
            levels == 5 || levels == 25,
            "Invalid levels: {levels}. Must be 5 or 25."
        );

        let (final_price_precision, final_size_precision) =
            if let (Some(price_prec), Some(size_prec)) = (price_precision, size_precision) {
                // Both precisions provided, use them directly
                (price_prec, size_prec)
            } else {
                // One or both precisions missing, detect only the missing ones
                let mut reader = create_csv_reader(&filepath)?;
                let mut record = StringRecord::new();
                let (detected_price, detected_size) =
                    Self::detect_precision_from_sample(&mut reader, &mut record, 10_000);
                (
                    price_precision.unwrap_or(detected_price),
                    size_precision.unwrap_or(detected_size),
                )

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Pass levels = 5 for Tardis derivative_ticker snapshot5 files or levels = 25 for snapshot25 files.
  2. Map your application's configured depth to the nearest supported value (5 or 25) before calling the streamer.
  3. Note that output is still OrderBookDepth10 (10 stored levels); a source levels of 5 yields only the first 5 populated levels.
  4. Validate the config value at startup with a clear check like levels == 5 || levels == 25.

Example fix

// before
let it = stream_order_book_depth10("snapshots.csv", 10_000, 10, None, None, None, None)?;
// after: levels must be 5 or 25 (output type stays OrderBookDepth10)
let it = stream_order_book_depth10("snapshots.csv", 10_000, 25, None, None, None, None)?;
Defensive patterns

Strategy: validation

Validate before calling

fn validate_levels(levels: u8) -> anyhow::Result<()> {
    anyhow::ensure!(levels == 5 || levels == 25, "levels must be 5 or 25, got {levels}");
    Ok(())
}
// call before constructing the stream
validate_levels(cfg.depth)?;

Type guard

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

Try / catch

if !is_supported_levels(cfg.depth) {
    return Err(anyhow::anyhow!("config depth {} unsupported; use 5 or 25", cfg.depth));
}
let it = stream_order_book_depth10(path, chunk, cfg.depth, None, None, None, None)?;

Prevention

When it happens

Trigger: Calling stream_order_book_depth10 (or stream_order_book_depth at 5/25 dispatch) with levels values such as 10, 0, 1, or 20; passing a user-config value like a book depth setting straight through without mapping to 5/25.

Common situations: Configuring a depth of 10 (confusing OrderBookDepth10 storage with the source levels); wiring an arbitrary config integer into the levels argument; copying an example and editing the levels value.

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/e0595bf2dae1f5cf. Report an issue: GitHub.