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

  1. Use na_position='last' (default) or na_position='first' — these are the only accepted values.
  2. Check the variable feeding na_position; default it to 'last' if None.
  3. 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

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


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)