t8y2/dbx · error

Delimited stream ended before providing a header

Error message

Delimited stream ended before providing a header

What it means

Raised when a delimited (CSV/TSV) import stream finishes without ever yielding a header row. The producer task ended (closed the channel) without sending columns, so the importer returns the generic fallback message instead of a concrete producer error. This guards the import pipeline from proceeding with zero columns.

Source

Thrown at crates/dbx-core/src/table_import.rs:6073

                let _ = producer.await;
                return Err(emit_import_error(
                    &mut progress_callback,
                    request,
                    0,
                    total_rows,
                    started_at,
                    "Delimited stream did not provide a header before data rows",
                ));
            }
            Some(Err(error)) => {
                let _ = producer.await;
                return Err(emit_import_error(&mut progress_callback, request, 0, total_rows, started_at, error));
            }
            None => {
                let error = producer
                    .await
                    .map_err(|error| error.to_string())?
                    .err()
                    .unwrap_or_else(|| "Delimited stream ended before providing a header".to_string());
                return Err(emit_import_error(&mut progress_callback, request, 0, total_rows, started_at, error));
            }
        };
        if columns.is_empty() {
            drop(receiver);
            let _ = producer.await;
            return Err(emit_import_error(
                &mut progress_callback,
                request,
                0,
                total_rows,
                started_at,
                "Import file has no columns in the selected row range",
            ));
        }
        if let Err(error) = mapping_indexes_for_columns(&columns, &request.mappings) {
            drop(receiver);

View on GitHub (pinned to c0390bff16)

Solutions

  1. Check the source file is non-empty and starts with a valid header row delimited by the configured separator
  2. Verify the import request's file path/handle points to real data, not an empty or truncated file
  3. Confirm the delimiter and encoding options match the actual file format
  4. Inspect any error the producer returned before the fallback message (the code surfaces producer.err() if present)

Example fix

// before
import_csv("empty.csv", ',') // stream ends, no header
// after
ensure file starts with: id,name,email\n... before calling the import API
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_delimited_has_header(path: &Path, delim: u8) -> Result<(), String> {
    let data = std::fs::read(path).map_err(|e| e.to_string())?;
    let trimmed: Vec<u8> = data.iter().copied().skip_while(|b| *b == 0xEF).collect(); // skip BOM-ish
    if trimmed.iter().all(|b| b.is_ascii_whitespace()) {
        return Err("file is empty or whitespace-only".into());
    }
    if !trimmed.contains(&b'\n') && !trimmed.contains(&delim) {
        return Err("no header row detected".into());
    }
    Ok(())
}

Type guard

fn has_header(first_record: Option<Vec<String>>) -> bool {
    matches!(first_record, Some(cols) if !cols.is_empty())
}

Try / catch

match importer.import_delimited(request) {
    Err(msg) if msg.contains("Delimited stream ended before providing a header") => {
        eprintln!("Source file has no header/rows: check the file and delimiter");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Importing an empty delimited file; a producer task that returns Ok(None) because the reader hit EOF immediately (e.g. blank or header-less CSV); a parsing backend that silently drops all rows so no header is ever emitted.

Common situations: Uploading a 0-byte CSV; a file containing only BOM or whitespace; an export tool that wrote nothing; wrong delimiter causing the parser to treat the whole file as one empty record; truncated download.

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/8f4269fb5d751a52. Report an issue: GitHub.