pandas-dev/pandas · error · ValueError
invalid na_position: {na_position!r}
Error message
invalid na_position: {na_position!r} What it means
Raised by Categorical.sort_values when na_position is not exactly 'last' or 'first'. The numpy-backed sort path (nargsort) only understands these two placements of missing values, so any other string is rejected before sorting begins. This is a strict input-contract violation surfaced as a ValueError.
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 71959b8cb9)
Solutions
- Pass exactly 'last' (default) or 'first' to na_position.
- Normalize external input with .lower() and validate against {'first','last'} before forwarding to sort_values.
Example fix
// before cat.sort_values(na_position='Last') # ValueError // after cat.sort_values(na_position='last')
Defensive patterns
Strategy: validation
Validate before calling
def normalize_na_position(value):
if value not in ('first', 'last'):
raise ValueError("na_position must be 'first' or 'last'")
return value Type guard
from typing import Literal
NaPosition = Literal['first', 'last']
def is_na_position(v: str) -> bool:
return v in ('first', 'last') Try / catch
try:
cat.sort_values(na_position=pos)
except ValueError as e:
if 'invalid na_position' in str(e):
cat.sort_values(na_position='last')
else:
raise Prevention
- Whitelist na_position input to {'first','last'} before forwarding to sort_values.
- Lowercase and strip user-supplied sort options.
When it happens
Trigger: Calling .sort_values(na_position=...) with a typo like 'Last', 'FIRST', 'top', 'bottom', None, or an empty string. Also triggered by dynamically passing a user-supplied value without normalization.
Common situations: User-facing code that forwards a config parameter straight to sort_values; locale-dependent casing; or confusion with DataFrame.sort_values which also only accepts 'first'/'last'.
Related errors
- codes need to be between -1 and len(categories)-1
- No such keys(s): {pat!r}
- {k} is not a valid identifier
- {k} is a python keyword
- Value must be an instance of {type_repr}
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/26d3a71a6780d3e6.
Report an issue: GitHub.