deepset-ai/haystack · error

CSVToDocument(row): content_column='{content_column}' not fo

Error message

CSVToDocument(row): content_column='{content_column}' not found in header for {source}. Available columns: {header}

What it means

In row mode the component is strict: the content_column supplied to run() must appear in the CSV header, otherwise it cannot know which field holds the document text. The error lists the actual header columns found.

Source

Thrown at haystack/components/converters/csv.py:178

                    )
            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)

        return {"documents": documents}

    # ----- helpers -----
    def _safe_value(self, value: Any) -> str:

View on GitHub (pinned to e318778c9b)

Solutions

  1. Set content_column to a name exactly matching a header field (case-sensitive).
  2. Inspect the 'Available columns' list in the message and pick the right one.
  3. Fix delimiter/quotechar so the header parses into the correct fields.
  4. Add or regenerate the header row in the CSV file.

Example fix

// before
csv_conv.run(sources=[f], content_column="Body")
// after (header is: id,text)
csv_conv.run(sources=[f], content_column="text")
Defensive patterns

Strategy: validation

Validate before calling

import csv, io
def ensure_content_column(data: bytes, content_column: str, delimiter: str = ",") -> None:
    header = next(csv.reader(io.StringIO(data.decode("utf-8")), delimiter=delimiter)) or []
    if content_column not in header:
        raise ValueError(f"content_column {content_column!r} not in header {header}")

Try / catch

try:
    result = conv.run(sources=[f], content_column=col)
except ValueError as e:
    if "not found in header" in str(e):
        col = col.lower()  # retry with normalized case or pick a column you parse from the header
        result = conv.run(sources=[f], content_column=col)
    else:
        raise

Prevention

When it happens

Trigger: run(sources=[...], content_column='body') on a CSV whose header row lacks 'body' — due to typo, case mismatch, wrong delimiter mangling the header, or a missing header row.

Common situations: Renamed columns upstream; case-sensitive mismatch ('Text' vs 'text'); delimiter mismatch causing the whole first line to be one field; CSV without a header at all.

Related errors


AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30). Data as JSON: /api/errors/3255726936dadb15. Report an issue: GitHub.