nautechsystems/nautilus_trader · error

CSV file is empty

Error message

CSV file is empty

What it means

TardisBookUpdateData::new requires at least one CSV record to determine the instrument ID and price/size precision defaults. The library throws this when the CSV file contains zero records (only a header or completely empty), since there is no first record to deserialize into TardisBookUpdateRecord.

Source

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

    ///
    /// # Errors
    ///
    /// Returns an error if the file cannot be opened or read.
    fn new<P: AsRef<Path>>(
        filepath: P,
        chunk_size: usize,
        price_precision: Option<u8>,
        size_precision: Option<u8>,
        instrument_id: Option<InstrumentId>,
        limit: Option<usize>,
    ) -> anyhow::Result<Self> {
        let mut reader = create_csv_reader(&filepath)?;
        let mut record = StringRecord::new();

        let first_record = if reader.read_record(&mut record)? {
            record.deserialize::<TardisBookUpdateRecord>(None)?
        } else {
            anyhow::bail!("CSV file is empty");
        };

        let final_instrument_id = instrument_id
            .unwrap_or_else(|| parse_instrument_id(&first_record.exchange, first_record.symbol));

        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 from sample including first record
                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. Check the file has data rows: `wc -l file.csv` (should be > 1 for a header + rows)
  2. Re-download the Tardis dataset for the correct date/venue/symbol
  3. Point TardisBookUpdateData::new at the correct non-empty CSV file
  4. If instrument_id/precisions are provided, verify the intended file wasn't replaced by an empty one

Example fix

// before
let data = TardisBookUpdateData::new(path, None, None, None)?;  // empty file
// after
assert!(std::fs::metadata(&path)?.len() > 0, "CSV file is empty");
let data = TardisBookUpdateData::new(path, None, None, None)?;
Defensive patterns

Strategy: validation

Validate before calling

fn csv_has_data(path: &Path) -> anyhow::Result<bool> {
    let content = std::fs::read_to_string(path)?;
    Ok(content.lines().skip_while(|l| l.trim().is_empty()).count() > 1) // header + rows
}
assert!(csv_has_data(&path)?, "CSV has no data rows");

Try / catch

let data = match TardisBookUpdateData::new(&path, None, None, None) {
    Ok(d) => d,
    Err(e) if e.to_string().contains("CSV file is empty") => {
        eprintln!("{} has no records; check the download", path.display());
        return Err(e);
    }
    Err(e) => return Err(e),
};

Prevention

When it happens

Trigger: Constructing TardisBookUpdateData::new with a filepath whose CSV has a header but no data rows, or is entirely empty (0 bytes).

Common situations: Tardis download returned an empty dataset for the requested date/venue; a filtered export removed all rows; the user pointed at the wrong (empty) file; an interrupted download produced a truncated file.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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