deepset-ai/haystack · error · ValueError
header_split_levels contains invalid values: {invalid}. All
Error message
header_split_levels contains invalid values: {invalid}. All levels must be integers between 1 and 6. What it means
MarkdownHeaderSplitter's __init__ checks that every entry in header_split_levels is an int in the range 1..6 (markdown heading levels). If any element fails this check, ValueError is raised listing the invalid values.
Source
Thrown at haystack/components/preprocessors/markdown_header_splitter.py:65
all levels `[1, 2, 3, 4, 5, 6]`.
:param secondary_split: Optional secondary split condition after header splitting.
Options are None, "word", "passage", "period", "line". Defaults to None.
:param split_length: The maximum number of units in each split when using secondary splitting. Defaults to 200.
:param split_overlap: The number of overlapping units for each split when using secondary splitting.
Defaults to 0.
:param split_threshold: The minimum number of units per split when using secondary splitting. Defaults to 0.
:param skip_empty_documents: Choose whether to skip documents with empty content. Default is True.
Set to False when downstream components in the Pipeline (like LLMDocumentContentExtractor) can extract text
from non-textual documents.
"""
if header_split_levels is None:
header_split_levels = [1, 2, 3, 4, 5, 6]
if not isinstance(header_split_levels, list) or len(header_split_levels) == 0:
raise ValueError("header_split_levels must be a non-empty list.")
invalid = [lvl for lvl in header_split_levels if not isinstance(lvl, int) or lvl < 1 or lvl > 6]
if invalid:
raise ValueError(
f"header_split_levels contains invalid values: {invalid}. All levels must be integers between 1 and 6."
)
if len(header_split_levels) != len(set(header_split_levels)):
raise ValueError("header_split_levels must not contain duplicate values.")
self.page_break_character = page_break_character
self.secondary_split = secondary_split
self.split_length = split_length
self.split_overlap = split_overlap
self.split_threshold = split_threshold
self.skip_empty_documents = skip_empty_documents
self.keep_headers = keep_headers
self.header_split_levels = header_split_levels
self._header_split_levels_set = set(header_split_levels)
self._header_pattern = re.compile(r"(?m)^(#{1,6}) (.+)$") # ATX-style .md-headers
# Matches fenced code blocks delimited by triple backticks (```) or triple tildes (~~~).
# Broken down:View on GitHub (pinned to e318778c9b)
Solutions
- Use only integers 1-6, e.g. header_split_levels=[1, 2, 3].
- Convert string values from config: [int(lvl) for lvl in raw_levels].
- Filter/validate levels before construction: levels = [l for l in levels if isinstance(l, int) and 1 <= l <= 6].
- Check for bool values too, since bool is a subclass of int (True==1 passes the current check); normalize with int() deliberately.
Example fix
// before MarkdownHeaderSplitter(header_split_levels=[0, 7]) MarkdownHeaderSplitter(header_split_levels=["1", "2"]) // after MarkdownHeaderSplitter(header_split_levels=[1, 2])
Defensive patterns
Strategy: validation
Validate before calling
levels = [int(l) for l in raw_levels if str(l).strip().isdigit()]
levels = [l for l in levels if 1 <= l <= 6]
if not levels:
levels = [1, 2, 3] Type guard
def all_levels_valid(levels) -> bool:
return all(isinstance(l, int) and not isinstance(l, bool) and 1 <= l <= 6 for l in levels) Try / catch
try:
splitter = MarkdownHeaderSplitter(header_split_levels=levels)
except ValueError as e:
raise ConfigError(f"header_split_levels invalid: {e}") from e Prevention
- Markdown heading levels are 1-6 (h1-h6); never use 0 or 7.
- Cast string config values with int() before passing.
- Filter out-of-range levels instead of passing them through.
When it happens
Trigger: Passing header_split_levels=[0], [7], ["1"], [1.5], [None], or any list containing non-int or out-of-range values to MarkdownHeaderSplitter.
Common situations: Off-by-one thinking (markdown levels are 1-based, not 0-based), reading levels from user input/config as strings, or confusing heading level with heading count.
Related errors
- 'response_fn' must return an assistant ChatMessage, got '{re
- Cannot stream multiple responses, please set n=1.
- A `ChatMessage` must contain at least one `TextContent`, `To
- top_k must be greater than 0.
- top_k must not be negative.
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/5332dd01e980dc69.
Report an issue: GitHub.