deepset-ai/haystack · error · ValueError

expected_chars_per_line must be at least 1.

Error message

expected_chars_per_line must be at least 1.

What it means

PythonCodeSplitter's __init__ requires expected_chars_per_line >= 1; this estimate drives length-based chunk calculations. Zero or negative estimates are invalid, so ValueError is raised.

Source

Thrown at haystack/components/preprocessors/python_code_splitter.py:130

            module-level docstring is kept in place since it is itself a top-level unit.
        :param preserve_class_definition: If ``True`` (default), chunks that contain class
            members but not the class header are prefixed with the bare class signature
            (decorators plus the ``class Foo(...):`` lines) in source order.
        :param secondary_split_overlap: Line overlap for the secondary splitter; only used
            in the oversized fallback. The primary AST split never adds overlap.
        :param secondary_split_length: Lines per chunk for the secondary splitter.
            Defaults to ``max_effective_lines`` when ``None``.
        :raises ValueError: If any parameter is invalid (negative, zero where positive is
            required, or ``min_effective_lines > max_effective_lines``).
        """
        if min_effective_lines < 1:
            raise ValueError("min_effective_lines must be at least 1.")
        if max_effective_lines < 1:
            raise ValueError("max_effective_lines must be at least 1.")
        if min_effective_lines > max_effective_lines:
            raise ValueError("min_effective_lines must not be greater than max_effective_lines.")
        if expected_chars_per_line < 1:
            raise ValueError("expected_chars_per_line must be at least 1.")
        if oversized_factor < 1:
            raise ValueError("oversized_factor must be at least 1.")
        if secondary_split_overlap < 0:
            raise ValueError("secondary_split_overlap must be non-negative.")
        if secondary_split_length is not None and secondary_split_length < 1:
            raise ValueError("secondary_split_length must be at least 1.")

        self.min_effective_lines = min_effective_lines
        self.max_effective_lines = max_effective_lines
        self.expected_chars_per_line = expected_chars_per_line
        self.oversized_factor = oversized_factor
        self.strip_docstrings = strip_docstrings
        self.preserve_class_definition = preserve_class_definition
        self.secondary_split_overlap = secondary_split_overlap
        self.secondary_split_length = secondary_split_length

    def _effective_lines(self, text: str) -> int:
        """Return the number of *effective lines* for ``text`` (see class docstring)."""

View on GitHub (pinned to e318778c9b)

Solutions

  1. Pass a realistic estimate, e.g. expected_chars_per_line=80.
  2. Omit the parameter to use the default.
  3. Clamp computed values: expected_chars_per_line=max(1, int(avg)).
  4. Fix the upstream statistics code that produced 0 (guard against empty inputs).

Example fix

// before
avg = sum(len(l) for l in lines) / max(1, len(lines)) if lines else 0
PythonCodeSplitter(expected_chars_per_line=int(avg))
// after
PythonCodeSplitter(expected_chars_per_line=max(1, int(avg)) if avg else 80)
Defensive patterns

Strategy: validation

Validate before calling

sample = [len(l) for l in lines] or [80]
expected_chars_per_line = max(1, int(sum(sample) / len(sample)))

Type guard

def is_valid_char_estimate(v) -> bool:
    return isinstance(v, int) and not isinstance(v, bool) and v >= 1

Try / catch

try:
    splitter = PythonCodeSplitter(expected_chars_per_line=estimate)
except ValueError as e:
    logging.warning("Invalid expected_chars_per_line (%s), using 80", e)
    splitter = PythonCodeSplitter(expected_chars_per_line=80)

Prevention

When it happens

Trigger: Calling PythonCodeSplitter(expected_chars_per_line=0) or negative, usually from a config default of 0, a failed statistic computation (e.g. mean over an empty corpus), or a division by a zero/huge denominator.

Common situations: Computing average line length from an empty sample, env/config placeholders left at 0, or mistaking the parameter for a boolean/flag.

Related errors


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