pandas-dev/pandas · error · TypeError

expected a string object, not {type(pat).__name__}

Error message

expected a string object, not {type(pat).__name__}

What it means

Raised by ArrowExtensionArray._str_rsplit when `pat` is not None and is not a Python str (e.g. bytes, an int, or a numpy scalar). The PyArrow split functions require a string pattern, so any non-str separator is rejected with TypeError before being forwarded to pc.split_pattern. Reached via Series.str.rsplit on a pyarrow-string Series.

Source

Thrown at pandas/core/arrays/arrow/array.py:3749

        if n in {-1, 0}:
            n = None
        if pat is None:
            split_func = pc.utf8_split_whitespace
        elif regex is True:
            split_func = functools.partial(pc.split_pattern_regex, pattern=pat)
        elif regex is False:
            split_func = functools.partial(pc.split_pattern, pattern=pat)
        # GH#58321: regex is None — infer: single-char literal, multi-char regex
        elif len(pat) == 1:
            split_func = functools.partial(pc.split_pattern, pattern=pat)
        else:
            split_func = functools.partial(pc.split_pattern_regex, pattern=pat)
        return self._from_pyarrow_array(split_func(self._pa_array, max_splits=n))

    def _str_rsplit(self, pat: str | None = None, n: int | None = -1) -> Self:
        if pat is not None and not isinstance(pat, str):
            msg = f"expected a string object, not {type(pat).__name__}"
            raise TypeError(msg)
        if n in {-1, 0}:
            n = None
        if pat is None:
            return self._from_pyarrow_array(
                pc.utf8_split_whitespace(self._pa_array, max_splits=n, reverse=True)
            )
        return self._from_pyarrow_array(
            pc.split_pattern(self._pa_array, pat, max_splits=n, reverse=True)
        )

    def _str_translate(self, table: dict[int, str]) -> Self:
        predicate = lambda val: val.translate(table)
        result = self._apply_elementwise(predicate)
        return self._from_pyarrow_array(pa.chunked_array(result))

    def _str_wrap(self, width: int, **kwargs) -> Self:
        kwargs["width"] = width
        tw = textwrap.TextWrapper(**kwargs)

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Pass a str separator: `s.str.rsplit(",", n=1)`.
  2. Decode bytes first: `sep.decode() if isinstance(sep, bytes) else sep`.
  3. Coerce loaded config values: `str(sep)` before calling rsplit.
  4. Double-check argument order: signature is `.str.rsplit(pat=None, n=-1)`.

Example fix

# before
s = pd.Series(["a,b,c"], dtype="string[pyarrow]")
s.str.rsplit(b",")  # TypeError: expected a string object, not bytes

# after
s.str.rsplit(",")
Defensive patterns

Strategy: type-guard

Validate before calling

def safe_rsplit(s, pat=None, n=-1):
    if pat is not None and not isinstance(pat, str):
        raise TypeError(f"pat must be str or None, got {type(pat).__name__}")
    return s.str.rsplit(pat, n=n)

Type guard

def is_str_or_none(v) -> bool:
    return v is None or isinstance(v, str)

Try / catch

try:
    out = s.str.rsplit(pat, n=n)
except TypeError as e:
    if "expected a string object" in str(e):
        out = s.str.rsplit(str(pat) if pat is not None else None, n=n)
    else:
        raise

Prevention

When it happens

Trigger: Calling `s.str.rsplit(separator)` where `separator` is bytes (`b","`), a numpy str_, an int, or None mishandled. Mixing up positional args so a non-str value lands in the `pat` slot also triggers it.

Common situations: Data pipelines that split on bytes read from binary protocols; config-driven separators loaded from JSON/YAML that come back as non-str; passing `n` into the `pat` position by mistake.

Related errors


AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07). Data as JSON: /api/errors/d71f4e8cd2dabb0d. Report an issue: GitHub.