deepset-ai/haystack · error
CSVToDocument: quotechar must be a single character.
Error message
CSVToDocument: quotechar must be a single character.
What it means
CSVToDocument validates at construction time that both delimiter and quotechar are exactly one character, because Python's csv module requires single-character dialect parameters. A longer (or empty) string cannot be passed to csv.reader/DictReader, so the component fails fast in __init__ rather than deep inside run().
Source
Thrown at haystack/components/converters/csv.py:82
:param conversion_mode:
- "file" (default): one Document per CSV file whose content is the raw CSV text.
- "row": convert each CSV row to its own Document (requires `content_column` in `run()`).
:param delimiter:
CSV delimiter used when parsing in row mode (passed to ``csv.DictReader``).
:param quotechar:
CSV quote character used when parsing in row mode (passed to ``csv.DictReader``).
"""
self.encoding = encoding
self.store_full_path = store_full_path
self.conversion_mode = conversion_mode
self.delimiter = delimiter
self.quotechar = quotechar
# Basic validation
if len(self.delimiter) != 1:
raise ValueError("CSVToDocument: delimiter must be a single character.")
if len(self.quotechar) != 1:
raise ValueError("CSVToDocument: quotechar must be a single character.")
@component.output_types(documents=list[Document])
def run(
self,
sources: list[str | Path | ByteStream],
*,
content_column: str | None = None,
meta: dict[str, Any] | list[dict[str, Any]] | None = None,
) -> dict[str, Any]:
"""
Converts CSV files to a Document (file mode) or to one Document per row (row mode).
:param sources:
List of file paths or ByteStream objects.
:param content_column:
**Required when** ``conversion_mode="row"``.
The column name whose values become ``Document.content`` for each row.
The column must exist in the CSV header.View on GitHub (pinned to e318778c9b)
Solutions
- Pass a single-character string, e.g. delimiter=';' or delimiter='\t'.
- For multi-character separators, preprocess/replace the separator before feeding the CSV, or use a different converter.
- Ensure the value read from config/env is unquoted and is str, not bytes or list.
- Check for accidental leading/trailing characters (e.g. '\t ' from YAML tab expansion).
Example fix
// before
csv_conv = CSVToDocument(delimiter="||", quotechar="\"")
// after
csv_conv = CSVToDocument(delimiter="|", quotechar="\"")
# or preprocess: text = text.replace("||", "|") before conversion Defensive patterns
Strategy: validation
Validate before calling
def validate_csv_dialect(delim, quote):
for name, v in (("delimiter", delim), ("quotechar", quote)):
if not isinstance(v, str) or len(v) != 1:
raise ValueError(f"CSVToDocument {name} must be a single character, got {v!r}")
validate_csv_dialect(delimiter, quotechar) Type guard
def is_single_char(v) -> bool:
return isinstance(v, str) and len(v) == 1 Try / catch
try:
conv = CSVToDocument(delimiter=delim, quotechar=quote)
except ValueError as e:
logger.error("Bad CSV dialect: %s", e)
conv = CSVToDocument() # fall back to defaults Prevention
- Validate single-character dialect params from config/env before constructing.
- Never wrap delimiters in extra quotes when storing them in YAML/env vars.
- Use '\t' escape for tab, not a literal multi-space string.
- Unit-test component construction with your actual config values.
When it happens
Trigger: Instantiating CSVToDocument(delimiter='||') or CSVToDocument(quotechar='') or any delimiter/quotechar with len != 1, e.g. multi-character separators or copying a quoted delimiter from config.
Common situations: Config supplied from YAML/env vars containing a quoted or two-char separator; users trying multi-char delimiters common in other tools (e.g. '|~|'); accidentally passing a Path or list instead of a string.
Understand the failure class
Background: "Invalid configuration value" and "Unsupported/Unknown setting value" errors: why libraries reject your config strings, numbers, and types — this error's family across 30 libraries.
Related errors
- CSVToDocument(row): 'content_column' is required in run() wh
- CSVToDocument(row): content_column='{content_column}' not fo
- No tools were configured for the Agent at initialization.
- CSVToDocument(row): could not parse CSV rows for {source}: {
- CSVToDocument(row): failed to process row {i} for {source}:
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/92f3002a7edb5b4d.
Report an issue: GitHub.