deepset-ai/haystack · error · ValueError
CSVToDocument: delimiter must be a single character.
Error message
CSVToDocument: delimiter must be a single character.
What it means
CSVToDocument.__init__ validates that the delimiter is exactly one character, since Python's csv module requires single-character delimiters. Passing a multi-character string fails fast at construction.
Source
Thrown at haystack/components/converters/csv.py:80
If True, the full path of the file is stored in the metadata of the document.
If False, only the file name is stored.
: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"``.View on GitHub (pinned to e318778c9b)
Solutions
- Pass a single character, e.g. delimiter=';', ',', or '\t'.
- Pre-process multi-character-delimited files into a single-char-delimited CSV before conversion.
- Strip whitespace from user/config-supplied delimiter values before constructing the converter.
Example fix
// before CSVToDocument(delimiter='||') // after import csv # or preprocess the file converter = CSVToDocument(delimiter=';')
Defensive patterns
Strategy: validation
Validate before calling
assert len(delimiter) == 1, f"delimiter must be a single character, got {delimiter!r}"
CSVToDocument(delimiter=delimiter) Type guard
def is_single_char(s: str) -> bool:
return isinstance(s, str) and len(s) == 1 Try / catch
try:
converter = CSVToDocument(delimiter=delimiter)
except ValueError as e:
if 'single character' in str(e):
converter = CSVToDocument(delimiter=delimiter.strip()[0])
else:
raise Prevention
- Strip whitespace from config/CLI-provided delimiters.
- Use explicit escapes like '\t' for tabs, not the word 'tab'.
- For multi-char separators, preprocess the file with a custom parser first.
When it happens
Trigger: CSVToDocument(delimiter='; ') or CSVToDocument(delimiter='\t ' where the source used a multi-char separator like '||' or a tab with trailing spaces).
Common situations: Copy-pasting separators from files that use multi-character delimiters; confusing tab ('\t') with the literal string 'tab'; configurable delimiter sourced from YAML/CLI containing whitespace.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- header_split_levels must be a non-empty list.
- min_effective_lines must be at least 1.
- max_effective_lines must be at least 1.
- expected_chars_per_line must be at least 1.
- oversized_factor must be at least 1.
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/97e542a2ee4d9511.
Report an issue: GitHub.