pandas-dev/pandas · error · IndexError

only integers, slices (`:`), ellipsis (`...`), numpy.newaxis

Error message

only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices

What it means

Raised in SparseArray.__getitem__ when the key is not an integer, not a tuple, not a slice, and not list-like (e.g. a string label or a float). SparseArray is positional-only, so label or non-integer-scalar indexing is invalid. The message is mirrored from numpy for familiarity.

Source

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

                # should be shifted. NB: here we are careful to also not shift by a
                # negative value for a case like [0, 1][-100:] where the start index
                # should be treated like 0
                if start > 0:
                    sp_index -= start

                # Length of our result should match applying this slice to a range
                # of the length of our original array
                new_len = len(range(len(self))[key])
                new_sp_index = make_sparse_index(new_len, sp_index, self.kind)
                return type(self)._simple_new(sp_vals, new_sp_index, self.dtype)
            else:
                indices = np.arange(len(self), dtype=np.int32)[key]
                return self.take(indices)

        elif not is_list_like(key):
            # e.g. "foo" or 2.5
            # exception message copied from numpy
            raise IndexError(
                r"only integers, slices (`:`), ellipsis (`...`), numpy.newaxis "
                r"(`None`) and integer or boolean arrays are valid indices"
            )

        else:
            if isinstance(key, SparseArray):
                # NOTE: If we guarantee that SparseDType(bool)
                # has only fill_value - true, false or nan
                # (see GH PR 44955)
                # we can apply mask very fast:
                if is_bool_dtype(key):
                    if isna(key.fill_value):
                        return self.take(key.sp_index.indices[key.sp_values])
                    if not key.fill_value:
                        return self.take(key.sp_index.indices)
                    n = len(self)
                    mask = np.full(n, True, dtype=np.bool_)
                    mask[key.sp_index.indices] = False

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Use integer positions: sparse_arr[int(i)].
  2. For label access, index the Series: pd.Series(sparse_arr, index=labels)['foo'].
  3. Coerce computed indices to int and validate they are in range.

Example fix

// before
val = sparse_arr['2020-01-01']
// after
val = pd.Series(sparse_arr, index=date_index)['2020-01-01']
Defensive patterns

Strategy: type-guard

Validate before calling

import pandas as pd
from pandas.api.types import is_integer, is_list_like

def getitem_sparse_safe(arr, key, labels=None):
    if isinstance(key, str) or (not is_integer(key) and not is_list_like(key) and not isinstance(key, slice)):
        if labels is None:
            raise IndexError('positional SparseArray; cannot use label key')
        return pd.Series(arr, index=labels)[key]
    return arr[int(key) if is_integer(key) else key]

Type guard

def is_positional_key(key) -> bool:
    from pandas.api.types import is_integer
    import numpy as np
    return is_integer(key) or isinstance(key, (slice, np.ndarray, list))

Try / catch

try:
    return arr[key]
except IndexError as e:
    if 'valid indices' in str(e):
        return pd.Series(arr, index=labels)[key]
    raise

Prevention

When it happens

Trigger: sparse_arr['foo']; sparse_arr[2.5]; passing a column label or datetime to index a SparseArray directly instead of going through the Series label index.

Common situations: Treating a SparseArray like a Series (.loc semantics); float indices from computations that should be int; label-based lookups forwarded to .array.

Related errors


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