pandas-dev/pandas · error · ValueError
Invalid side: . Side must be one of 'left', 'right', 'both
Error message
Invalid side: {side}. Side must be one of 'left', 'right', 'both' What it means
ValueError raised in _str_pad of the ArrowStringArray mixin when the side argument is not one of 'left', 'right', or 'both'. The pyarrow backend uses 'both' for center-padding; 'center' is not accepted.
Solutions
- Use side='both' for center padding: s.str.pad(10, side='both').
- Use the higher-level s.str.center(10) which maps to side='both' internally.
- Confirm the Series dtype; the same call works on object dtype but pyarrow enforces the documented enum.
Example fix
# before s.str.pad(10, side='center') # after s.str.center(10) # or s.str.pad(10, side='both')
Defensive patterns
Strategy: validation
Validate before calling
VALID_SIDES = {'left', 'right', 'both'}
def safe_pad(s, width, side, fillchar=' '):
if side not in VALID_SIDES:
side = 'both' if side == 'center' else 'left'
return s.str.pad(width, side=side, fillchar=fillchar) Try / catch
try:
s.str.pad(10, side=side)
except ValueError as e:
if 'Invalid side' in str(e):
s.str.center(10) # map center->both
else:
raise Prevention
- Use s.str.center / s.str.ljust / s.str.rjust helpers which avoid the side enum.
- Validate side against {'left','right','both'} before calling str.pad.
When it happens
Trigger: s.str.pad(width=10, side='center') on a pyarrow-backed string Series (dtype StringDtype(storage='pyarrow')).
Common situations: Code that worked on object dtype strings and used 'center' verbatim; users assuming pandas mirrors Python's str.center naming.
Related errors
- invalid normalization form
- contains not implemented with
- replace is not supported with a re.Pattern, callable repl…
- ambiguous is not supported.
- is not supported
AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11).
Data as JSON: /api/errors/8fdc20005d7b61a6.
Report an issue: GitHub.
Appendix: 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 3b7651241d)