{"record":{"id":"416de25fbc509293","repo":"pandas-dev/pandas","slug":"empty-separator","errorCode":null,"errorMessage":"empty separator","messagePattern":"empty separator","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/_arrow_string_mixins.py","lineNumber":510,"sourceCode":"        result = result.cast(pa.int64())\n        return self._convert_int_result(result)\n\n    def _str_partition_expand(self, sep: str) -> pa.ChunkedArray:\n        \"\"\"\n        Split each string on the first occurrence of ``sep``.\n\n        Returns a ``list<string>`` array holding one three-element list per row\n        -- the part before the separator, the separator, and the part after --\n        which ``StringMethods._wrap_result`` expands into three columns. Rows\n        without ``sep`` get two empty strings, matching ``str.partition``.\n\n        The caller wraps this in an :class:`ArrowExtensionArray`; the rows are\n        lists, so it is not of the calling array's own type.\n        \"\"\"\n        if not sep:\n            # pyarrow reports this as \"Empty separator\"; keep str.partition's\n            #  wording so every dtype raises the same way\n            raise ValueError(\"empty separator\")\n\n        str_type = self._pa_array.type\n        chunks = [\n            self._partition_chunk(chunk, sep, str_type)\n            for chunk in self._pa_array.chunks\n        ]\n        return pa.chunked_array(chunks, type=pa.list_(str_type))\n\n    @staticmethod\n    def _partition_chunk(chunk: pa.Array, sep: str, str_type: pa.DataType) -> pa.Array:\n        \"\"\"\n        Build the ``list<string>`` rows for one chunk of :meth:`_str_partition_expand`.\n\n        Working a chunk at a time keeps the concatenation below within the\n        offset width of ``str_type``, which matters for columns near the 2 GiB\n        limit of 32-bit ``string``.\n        \"\"\"\n        # max_splits=1 gives [before] when sep is absent, else [before, after];","sourceCodeStart":492,"sourceCodeEnd":528,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/_arrow_string_mixins.py#L492-L528","documentation":"Raised by the pyarrow-backed string mixin's `_str_partition_expand` when the `sep` argument is empty/falsy. pandas intentionally re-raises pyarrow's 'Empty separator' using the wording Python's built-in `str.partition` uses ('empty separator') so every string dtype (object, StringDtype, ArrowDtype[str]) raises identically. It is a `ValueError`. The guard runs before any pyarrow compute call, so no partial work is done.","triggerScenarios":"Calling `Series.str.partition('')` or `Series.str.rpartition('')` on a Series whose dtype is `string[pyarrow]` (ArrowExtensionArray of strings). Also reachable via `.str.partition(sep='')` where `sep` resolves to an empty string at runtime, e.g. `sep=some_var or ''`.","commonSituations":"Passing a user-supplied separator that was not validated; using a default of `''` instead of `None`; migrating from object dtype to `string[pyarrow]` and discovering the empty-sep path now goes through this mixin.","solutions":["Pass a non-empty separator string to `Series.str.partition` / `Series.str.rpartition`.","If the separator comes from user input or config, validate `if not sep: raise ValueError(...)` before calling and surface a clearer message.","Handle the empty-separator case explicitly in your code (e.g. return the original string in column 0 and empty strings in columns 1-2) rather than relying on the library."],"exampleFix":"// before\ns.str.partition(sep=user_sep)   # user_sep == '' -> ValueError\n\n// after\nif not user_sep:\n    raise ValueError('separator must be non-empty')\ns.str.partition(sep=user_sep)","handlingStrategy":"validation","validationCode":"if not sep:\n    raise ValueError('separator must be a non-empty string')\ns.str.partition(sep=sep)","typeGuard":"def is_nonempty_str(s: object) -> bool:\n    return isinstance(s, str) and len(s) > 0","tryCatchPattern":"try:\n    parts = s.str.partition(sep)\nexcept ValueError as e:\n    if 'empty separator' in str(e):\n        raise ValueError('Provide a non-empty separator') from e\n    raise","preventionTips":["Validate user-supplied separators before passing to .str.partition","Prefer None as 'unset' sentinel and translate to a real separator"],"tags":["string","pyarrow","str-accessor","validation"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}