{"record":{"id":"8f4269fb5d751a52","repo":"t8y2/dbx","slug":"delimited-stream-ended-before-providing-a-header","errorCode":null,"errorMessage":"Delimited stream ended before providing a header","messagePattern":"Delimited stream ended before providing a header","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/dbx-core/src/table_import.rs","lineNumber":6073,"sourceCode":"                let _ = producer.await;\n                return Err(emit_import_error(\n                    &mut progress_callback,\n                    request,\n                    0,\n                    total_rows,\n                    started_at,\n                    \"Delimited stream did not provide a header before data rows\",\n                ));\n            }\n            Some(Err(error)) => {\n                let _ = producer.await;\n                return Err(emit_import_error(&mut progress_callback, request, 0, total_rows, started_at, error));\n            }\n            None => {\n                let error = producer\n                    .await\n                    .map_err(|error| error.to_string())?\n                    .err()\n                    .unwrap_or_else(|| \"Delimited stream ended before providing a header\".to_string());\n                return Err(emit_import_error(&mut progress_callback, request, 0, total_rows, started_at, error));\n            }\n        };\n        if columns.is_empty() {\n            drop(receiver);\n            let _ = producer.await;\n            return Err(emit_import_error(\n                &mut progress_callback,\n                request,\n                0,\n                total_rows,\n                started_at,\n                \"Import file has no columns in the selected row range\",\n            ));\n        }\n        if let Err(error) = mapping_indexes_for_columns(&columns, &request.mappings) {\n            drop(receiver);","sourceCodeStart":6055,"sourceCodeEnd":6091,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/crates/dbx-core/src/table_import.rs#L6055-L6091","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the source file is non-empty and starts with a valid header row delimited by the configured separator","Verify the import request's file path/handle points to real data, not an empty or truncated file","Confirm the delimiter and encoding options match the actual file format","Inspect any error the producer returned before the fallback message (the code surfaces producer.err() if present)"],"exampleFix":"// before\nimport_csv(\"empty.csv\", ',') // stream ends, no header\n// after\nensure file starts with: id,name,email\\n... before calling the import API","handlingStrategy":"validation","validationCode":"fn ensure_delimited_has_header(path: &Path, delim: u8) -> Result<(), String> {\n    let data = std::fs::read(path).map_err(|e| e.to_string())?;\n    let trimmed: Vec<u8> = data.iter().copied().skip_while(|b| *b == 0xEF).collect(); // skip BOM-ish\n    if trimmed.iter().all(|b| b.is_ascii_whitespace()) {\n        return Err(\"file is empty or whitespace-only\".into());\n    }\n    if !trimmed.contains(&b'\\n') && !trimmed.contains(&delim) {\n        return Err(\"no header row detected\".into());\n    }\n    Ok(())\n}","typeGuard":"fn has_header(first_record: Option<Vec<String>>) -> bool {\n    matches!(first_record, Some(cols) if !cols.is_empty())\n}","tryCatchPattern":"match importer.import_delimited(request) {\n    Err(msg) if msg.contains(\"Delimited stream ended before providing a header\") => {\n        eprintln!(\"Source file has no header/rows: check the file and delimiter\");\n    }\n    other => other?,\n}","preventionTips":["Check file size > 0 before importing","Validate the first line contains the expected delimiter and column names","Verify sheet/file selection and encoding options","Catch truncated downloads with checksum/size checks"],"tags":["csv","import","streaming","empty-input"],"backgroundTag":"empty-header-row","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}