pandas-dev/pandas · error · ValueError

Encountered an NA value with skipna=False

Error message

Encountered an NA value with skipna=False

What it means

Raised by SparseArray.argmax when skipna=False and the array contains NA (self._hasna). Position-of-max is undefined when an NA is present and the user has opted out of skipping them, so pandas raises rather than returning a possibly-meaningless position. The check runs before _argmin_argmax to fail fast.

Source

Thrown at pandas/core/arrays/sparse/array.py:1848

        candidate = index[_candidate]

        if isna(self.fill_value):
            return candidate
        if kind == "argmin" and self[candidate] < self.fill_value:
            return candidate
        if kind == "argmax" and self[candidate] > self.fill_value:
            return candidate
        _loc = self._first_fill_value_loc()
        if _loc == -1:
            # fill_value doesn't exist
            return candidate
        else:
            return _loc

    def argmax(self, skipna: bool = True) -> int:
        validate_bool_kwarg(skipna, "skipna")
        if not skipna and self._hasna:
            raise ValueError("Encountered an NA value with skipna=False")
        return self._argmin_argmax("argmax")

    def argmin(self, skipna: bool = True) -> int:
        validate_bool_kwarg(skipna, "skipna")
        if not skipna and self._hasna:
            raise ValueError("Encountered an NA value with skipna=False")
        return self._argmin_argmax("argmin")

    # ------------------------------------------------------------------------
    # Ufuncs
    # ------------------------------------------------------------------------

    _HANDLED_TYPES = (np.ndarray, numbers.Number)

    def __array_ufunc__(self, ufunc: np.ufunc, method: str, *inputs, **kwargs):
        out = kwargs.get("out", ())

        for x in inputs + out:

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Use the default skipna=True if NA positions are not meaningful: sparse_arr.argmax().
  2. Pre-check: if sparse_arr._hasna: handle NA explicitly before calling argmax(skipna=False).
  3. Drop NA first: sparse_arr.dropna().argmax(skipna=False).

Example fix

// before
pos = pd.arrays.SparseArray([1.0, np.nan, 2.0]).argmax(skipna=False)  # raises

// after
pos = pd.arrays.SparseArray([1.0, np.nan, 2.0]).argmax()  # skipna=True
Defensive patterns

Strategy: validation

Validate before calling

def argmax_safe(arr, skipna=True):
    if not skipna and arr._hasna:
        # NA present and skipna disabled: decide policy explicitly
        raise ValueError('NA present with skipna=False; cannot compute argmax')
    return arr.argmax(skipna=skipna)

Type guard

def can_argmax_skipna_false(arr) -> bool:
    return not arr._hasna

Try / catch

try:
    pos = arr.argmax(skipna=False)
except ValueError as e:
    if 'NA value with skipna=False' in str(e):
        pos = arr.argmax()  # fall back to skipna=True
    else:
        raise

Prevention

When it happens

Trigger: pd.arrays.SparseArray([1.0, np.nan, 2.0]).argmax(skipna=False), or Series.idxmax(skipna=False) on a sparse Series with NaN fill or NaN sparse values.

Common situations: Calling idxmax/argmax with skipna=False expecting a 'return NaN position' semantics, or after reindexing that introduced NA fill values.

Related errors


AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07). Data as JSON: /api/errors/3dd9817d72acd762. Report an issue: GitHub.