pandas-dev/pandas · error · ValueError
invalid na_position
Error message
invalid na_position: {na_position!r} What it means
Raised inside Categorical.sort_values when the na_position argument is neither 'last' nor 'first'. The argument is validated before nargsort is dispatched because the downstream Cython sort only knows those two sentinel strings. Any other value (including typos, wrong case, or None) is rejected up front.
Solutions
- Use na_position='last' (default) or na_position='first' — these are the only accepted values.
- Check the variable feeding na_position; default it to 'last' if None.
- If building a UI/config layer, validate against {'first','last'} before passing through.
Example fix
# before cat.sort_values(na_position='end') # ValueError # after cat.sort_values(na_position='last')
Defensive patterns
Strategy: validation
Validate before calling
na_position = na_position or 'last'
assert na_position in ('first', 'last'), f"na_position must be 'first' or 'last', got {na_position!r}"
cat.sort_values(na_position=na_position) Type guard
def valid_na_position(v: object) -> str:
if v not in ('first', 'last'):
raise ValueError(f"na_position must be 'first' or 'last', got {v!r}")
return v # type: ignore[return-value] Try / catch
try:
cat.sort_values(na_position=na_pos)
except ValueError as e:
if 'invalid na_position' in str(e):
cat.sort_values(na_position='last')
else:
raise Prevention
- Default na_position explicitly to 'last' in wrapper functions.
- Validate config-driven sort params against {'first','last'} at the config boundary.
When it happens
Trigger: cat.sort_values(na_position='end'), cat.sort_values(na_position='First') (wrong case), cat.sort_values(na_position=None), cat.sort_values(na_position='top'). Also reached indirectly via DataFrame.sort_values on a categorical column with an invalid na_position.
Common situations: User assumes NumPy/SQL vocabulary ('DESC','NULLS FIRST') applies. Copy-pasting from code that used a different library. Passing a variable that was meant to be 'last' but is None due to an unset config.
Related errors
- Input must be list-like
- > 1 ndim Categorical are not supported at this time
- Accumulation not supported for
- at least 'start' or 'end' should be specified if a 'period'…
- axis is out of bounds for array of dimension
AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11).
Data as JSON: /api/errors/26d3a71a6780d3e6.
Report an issue: GitHub.
Appendix: source
Thrown at pandas/core/arrays/categorical.py:2159
>>> c
[NaN, 2, 2, NaN, 5]
Categories (2, int64): [2, 5]
>>> c.sort_values()
[2, 2, 5, NaN, NaN]
Categories (2, int64): [2, 5]
>>> c.sort_values(ascending=False)
[5, 2, 2, NaN, NaN]
Categories (2, int64): [2, 5]
>>> c.sort_values(na_position="first")
[NaN, NaN, 2, 2, 5]
Categories (2, int64): [2, 5]
>>> c.sort_values(ascending=False, na_position="first")
[NaN, NaN, 5, 2, 2]
Categories (2, int64): [2, 5]
"""
inplace = validate_bool_kwarg(inplace, "inplace")
if na_position not in ["last", "first"]:
raise ValueError(f"invalid na_position: {na_position!r}")
sorted_idx = nargsort(self, ascending=ascending, na_position=na_position)
if not inplace:
codes = self._codes[sorted_idx]
return self._from_backing_data(codes)
self._codes[:] = self._codes[sorted_idx]
return None
def _rank(
self,
*,
axis: AxisInt = 0,
method: RankMethod = "average",
na_option: RankNaOption = "keep",
ascending: bool = True,
pct: bool = False,
):View on GitHub (pinned to 3b7651241d)