deepset-ai/haystack · error · ValueError

All separators must be strings.

Error message

All separators must be strings.

What it means

RecursiveSplitter accepts a 'separators' list used to recursively split text; every entry must be a str. Non-string entries (None, ints, regex objects, lists) cannot be used as string separators, so _check_params rejects the list at construction.

Source

Thrown at haystack/components/preprocessors/recursive_splitter.py:121

        """
        if self._is_warmed_up:
            return
        if "sentence" in self.separators:
            self.nltk_tokenizer = self._get_custom_sentence_tokenizer(self.sentence_splitter_params)
        if self.split_units == "token":
            tiktoken_imports.check()
            self.tiktoken_tokenizer = tiktoken.get_encoding("o200k_base")
        self._is_warmed_up = True

    def _check_params(self) -> None:
        if self.split_length < 1:
            raise ValueError("Split length must be at least 1 character.")
        if self.split_overlap < 0:
            raise ValueError("split_overlap must be greater than or equal to 0.")
        if self.split_overlap >= self.split_length:
            raise ValueError("Overlap cannot be greater than or equal to the chunk size.")
        if not all(isinstance(separator, str) for separator in self.separators):
            raise ValueError("All separators must be strings.")

    @staticmethod
    def _get_custom_sentence_tokenizer(sentence_splitter_params: dict[str, Any]) -> Any:
        from haystack.components.preprocessors.sentence_tokenizer import SentenceSplitter

        return SentenceSplitter(**sentence_splitter_params)

    def _split_chunk(self, current_chunk: str) -> tuple[str, str]:
        """
        Splits a chunk based on the split_length and split_units attribute.

        :param current_chunk: The current chunk to be split.
        :returns:
            A tuple containing the current chunk and the remaining chunk.
        """
        if self.split_units == "word":
            words = current_chunk.split()
            current_chunk = " ".join(words[: self.split_length])

View on GitHub (pinned to e318778c9b)

Solutions

  1. Pass a list of plain strings: separators=['\n\n', '\n', '.', ' '].
  2. Validate/coerce config values: separators=[str(s) for s in raw_separators if s is not None].
  3. If only defaults are wanted, omit the separators parameter.

Example fix

// before
splitter = RecursiveSplitter(separators=['\n\n', None, 3])
// after
splitter = RecursiveSplitter(separators=['\n\n', '\n', '. '])
Defensive patterns

Strategy: validation

Validate before calling

if not all(isinstance(s, str) for s in separators):
    raise TypeError('All separators must be strings')

Type guard

def all_str_separators(seps) -> bool:
    return isinstance(seps, list) and all(isinstance(s, str) for s in seps)

Try / catch

try:
    splitter = RecursiveSplitter(separators=seps)
except ValueError as e:
    logger.error('Invalid separators: %s', e)
    splitter = RecursiveSplitter()  # default separators

Prevention

When it happens

Trigger: RecursiveSplitter(separators=['\n\n', None]), passing a single string instead of a list of strings mixed with non-str items, or serializing/deserializing configs where a separator became null.

Common situations: Pipeline YAML where a separator value is unquoted and parsed as a number/bool/null; JSON configs with null entries; building separators programmatically from mixed sources.

Understand the failure class

Background: "must be positive", "Invalid value": how libraries reject invalid parameter values (ValueError, ArgumentError, INVALID_PARAMETER_VALUE) — this error's family across 28 libraries.

Related errors


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