deepset-ai/haystack · error · RuntimeError
CSVToDocument(row): could not parse CSV rows for {source}: {
Error message
CSVToDocument(row): could not parse CSV rows for {source}: {e} What it means
When DictReader construction fails, CSVToDocument wraps any exception in a RuntimeError that names the offending source. This is a wrapper around parsing errors such as IO failures or bad dialect parameters interacting with the data.
Source
Thrown at haystack/components/converters/csv.py:173
if size_bytes > _ROW_MODE_SIZE_WARN_BYTES:
logger.warning(
"CSVToDocument(row): parsing a large CSV (~{mb:.1f} MB). "
"Consider chunking/streaming if you hit memory issues.",
mb=size_bytes / (1024 * 1024),
)
except Exception:
pass
# Create DictReader; if this fails, raise (no fallback)
try:
# ``restkey`` ensures surplus fields on ragged rows (rows with more values than the
# header, e.g. an unquoted comma inside a value) land under an explicit string key
# instead of the default ``None`` key, which would break ``Document`` id generation.
reader = csv.DictReader(
io.StringIO(data), delimiter=self.delimiter, quotechar=self.quotechar, restkey="extra_columns"
)
except Exception as e:
raise RuntimeError(f"CSVToDocument(row): could not parse CSV rows for {source}: {e}") from e
# Validate header contains content_column; strict error if missing
header = reader.fieldnames or []
if content_column not in header:
raise ValueError(
f"CSVToDocument(row): content_column='{content_column}' not found in header "
f"for {source}. Available columns: {header}"
)
# Build documents; if a row processing fails, raise immediately (no skip)
for i, row in enumerate(reader):
try:
doc = self._build_document_from_row(
row=row, base_meta=merged_metadata, row_index=i, content_column=content_column
)
except Exception as e:
raise RuntimeError(f"CSVToDocument(row): failed to process row {i} for {source}: {e}") from e
documents.append(doc)View on GitHub (pinned to e318778c9b)
Solutions
- Read the chained exception (from e) message to identify the root cause.
- Verify the file is valid CSV text in the expected encoding (decode/convert to UTF-8 first).
- Check that delimiter/quotechar match the actual file dialect.
- Open the file in a CSV viewer/pandas to confirm it parses.
Defensive patterns
Strategy: try-catch
Validate before calling
import csv, io
def is_parseable_csv(data: bytes, delimiter: str = ",", quotechar: str = '"') -> bool:
try:
text = data.decode("utf-8")
next(csv.reader(io.StringIO(text), delimiter=delimiter, quotechar=quotechar))
return True
except (UnicodeDecodeError, csv.Error, StopIteration):
return False Type guard
def looks_like_csv(data: bytes) -> bool:
try:
text = data.decode("utf-8")
except UnicodeDecodeError:
return False
first = text.splitlines()[0] if text else ""
return ("," in first or ";" in first or "\t" in first) Try / catch
try:
result = conv.run(sources=[stream])
except RuntimeError as e:
logger.exception("CSV parse failed: %s", e) # cause is chained via __cause__
raise Prevention
- Ensure sources are UTF-8 text CSVs, not Excel/binary exports.
- Verify delimiter/quotechar against a sample of the real file.
- Pre-decode bytes and normalize encoding before conversion.
- Inspect e.__cause__ to find the underlying csv error.
When it happens
Trigger: run() with conversion_mode='row' on a source whose CSV cannot be parsed by csv.DictReader with the configured delimiter/quotechar — e.g. a decoding error, an IO error opening the stream, or malformed dialect chars.
Common situations: Binary/encoded (non-UTF-8) CSV bytes; wrong delimiter making the parser raise; corrupted downloads; passing ByteStream data that is actually JSON or Excel.
Related errors
- CSVToDocument: quotechar must be a single character.
- CSVToDocument(row): 'content_column' is required in run() wh
- CSVToDocument(row): content_column='{content_column}' not fo
- CSVToDocument(row): failed to process row {i} for {source}:
- All lists in the JSON must have the same length
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/8f985fac2b6340e4.
Report an issue: GitHub.