{"record":{"id":"e1e05f877714a5ac","repo":"deepset-ai/haystack","slug":"all-separators-must-be-strings","errorCode":null,"errorMessage":"All separators must be strings.","messagePattern":"All separators must be strings\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"haystack/components/preprocessors/recursive_splitter.py","lineNumber":121,"sourceCode":"        \"\"\"\n        if self._is_warmed_up:\n            return\n        if \"sentence\" in self.separators:\n            self.nltk_tokenizer = self._get_custom_sentence_tokenizer(self.sentence_splitter_params)\n        if self.split_units == \"token\":\n            tiktoken_imports.check()\n            self.tiktoken_tokenizer = tiktoken.get_encoding(\"o200k_base\")\n        self._is_warmed_up = True\n\n    def _check_params(self) -> None:\n        if self.split_length < 1:\n            raise ValueError(\"Split length must be at least 1 character.\")\n        if self.split_overlap < 0:\n            raise ValueError(\"split_overlap must be greater than or equal to 0.\")\n        if self.split_overlap >= self.split_length:\n            raise ValueError(\"Overlap cannot be greater than or equal to the chunk size.\")\n        if not all(isinstance(separator, str) for separator in self.separators):\n            raise ValueError(\"All separators must be strings.\")\n\n    @staticmethod\n    def _get_custom_sentence_tokenizer(sentence_splitter_params: dict[str, Any]) -> Any:\n        from haystack.components.preprocessors.sentence_tokenizer import SentenceSplitter\n\n        return SentenceSplitter(**sentence_splitter_params)\n\n    def _split_chunk(self, current_chunk: str) -> tuple[str, str]:\n        \"\"\"\n        Splits a chunk based on the split_length and split_units attribute.\n\n        :param current_chunk: The current chunk to be split.\n        :returns:\n            A tuple containing the current chunk and the remaining chunk.\n        \"\"\"\n        if self.split_units == \"word\":\n            words = current_chunk.split()\n            current_chunk = \" \".join(words[: self.split_length])","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/components/preprocessors/recursive_splitter.py#L103-L139","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass a list of plain strings: separators=['\\n\\n', '\\n', '.', ' '].","Validate/coerce config values: separators=[str(s) for s in raw_separators if s is not None].","If only defaults are wanted, omit the separators parameter."],"exampleFix":"// before\nsplitter = RecursiveSplitter(separators=['\\n\\n', None, 3])\n// after\nsplitter = RecursiveSplitter(separators=['\\n\\n', '\\n', '. '])","handlingStrategy":"validation","validationCode":"if not all(isinstance(s, str) for s in separators):\n    raise TypeError('All separators must be strings')","typeGuard":"def all_str_separators(seps) -> bool:\n    return isinstance(seps, list) and all(isinstance(s, str) for s in seps)","tryCatchPattern":"try:\n    splitter = RecursiveSplitter(separators=seps)\nexcept ValueError as e:\n    logger.error('Invalid separators: %s', e)\n    splitter = RecursiveSplitter()  # default separators","preventionTips":["Quote separator strings in YAML so '\\n' is not mangled and values stay strings.","Filter None entries after deserializing JSON configs: [s for s in raw if isinstance(s, str)].","Keep a shared constants module of separator lists instead of inline literals."],"tags":["python","validation","typeerror","constructor-argument","haystack"],"backgroundTag":"invalid-parameter-value","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}