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 canonicalView on GitHub (pinned to 71959b8cb9)
Solutions
- Pass side as one of the lowercase strings 'left', 'right', 'both'.
- If you used str.center/str.ljust/str.rjust, prefer those over calling _str_pad directly with a custom side.
- 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
- Normalize side to lowercase before passing
- Prefer str.ljust/str.rjust/str.center which infer side for you
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
- invalid normalization form
- replace is not supported with a re.Pattern, callable repl, c
- contains not implemented with {flags=}
- key must be an int or slice, got {type(key).__name__}
- {pat=} must contain a symbolic group name.
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/8fdc20005d7b61a6.
Report an issue: GitHub.