pandas-dev/pandas · error · ValueError

Invalid side: {side}. Side must be one of 'left', 'right', '

Error message

Invalid side: {side}. Side must be one of 'left', 'right', 'both'

What it means

Raised by the pyarrow-backed string `.str.pad()` when `side` is not 'left', 'right', or 'both'. The method maps each side to a distinct pyarrow compute kernel (utf8_lpad / utf8_rpad / utf8_center); an unknown side has no kernel and is rejected up front. This also affects str.center/str.ljust/str.rjust, which delegate to _str_pad. It is a hard ValueError on string[pyarrow] Series.

Source

Thrown at pandas/core/arrays/_arrow_string_mixins.py:166

            pa_pad = pc.utf8_lpad
        elif side == "right":
            pa_pad = pc.utf8_rpad
        elif side == "both":
            if pa_version_under17p0:
                # GH#59624 fall back to object dtype
                from pandas import array

                obj_arr = self.astype(object, copy=False)  # type: ignore[attr-defined]
                obj = array(obj_arr, dtype=object)
                result = obj._str_pad(width, side, fillchar)  # type: ignore[attr-defined]
                return type(self)._from_sequence(result, dtype=self.dtype)  # type: ignore[attr-defined]
            else:
                # GH#54792
                # https://github.com/apache/arrow/issues/15053#issuecomment-2317032347
                lean_left = (width % 2) == 0
                pa_pad = partial(pc.utf8_center, lean_left_on_odd_padding=lean_left)
        else:
            raise ValueError(
                f"Invalid side: {side}. Side must be one of 'left', 'right', 'both'"
            )
        return self._from_pyarrow_array(
            pa_pad(self._pa_array, width=width, padding=fillchar)
        )

    def _str_zfill(self, width: int) -> Self:
        if pa_version_under21p0:
            predicate = lambda val: val.zfill(width)
            result = self._apply_elementwise(predicate)
            return self._from_pyarrow_array(pa.chunked_array(result))
        return self._from_pyarrow_array(pc.utf8_zfill(self._pa_array, width))

    def _str_normalize(self, form: Literal["NFC", "NFD", "NFKC", "NFKD"]) -> Self:
        if form not in ("NFC", "NFD", "NFKC", "NFKD"):
            raise ValueError("invalid normalization form")
        if form in ("NFC", "NFKC"):
            # GH#64359 pc.utf8_normalize only decomposes; it skips the canonical

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Pass side as one of the lowercase strings 'left', 'right', 'both'.
  2. If you used str.center/str.ljust/str.rjust, prefer those over calling _str_pad directly with a custom side.
  3. Whitelist-validate side against {'left','right','both'} before the call when it comes from user/config input.

Example fix

// before
s.str.pad(5, "Left")
// after
s.str.pad(5, "left")
Defensive patterns

Strategy: validation

Validate before calling

def safe_pad(s, width, side="left", fillchar=" "):
    if side not in ("left", "right", "both"):
        raise ValueError(f"side must be one of left/right/both, got {side!r}")
    return s.str.pad(width, side=side, fillchar=fillchar)

Prevention

When it happens

Trigger: Calling s.str.pad(width, side='Left'), side='middle', side=None, or passing fillchar into the side slot positionally, on a Series whose dtype is string[pyarrow] or str backed by pyarrow.

Common situations: Case-sensitivity typos ('Left' vs 'left'), localized side strings read from config, or argument-order mistakes when calling pad(width, side, fillchar) positionally.

Related errors


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