pandas-dev/pandas · error · IndexError

out of bounds value in 'indices'.

Error message

out of bounds value in 'indices'.

What it means

IndexError from SparseArray._take_with_fill when allow_fill=True and the maximum index is >= len(self). The upper bound for fill-mode take is len(self)-1; -1 is reserved as the fill sentinel.

Source

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

        else:
            return self._take_without_fill(indices)

        return type(self)(
            result, fill_value=self.fill_value, kind=self.kind, dtype=dtype
        )

    def _take_with_fill(self, indices, fill_value=None) -> np.ndarray:
        if fill_value is None:
            fill_value = self.dtype.na_value

        if indices.min() < -1:
            raise ValueError(
                "Invalid value in 'indices'. Must be between -1 "
                "and the length of the array."
            )

        if indices.max() >= len(self):
            raise IndexError("out of bounds value in 'indices'.")

        if len(self) == 0:
            # Empty... Allow taking only if all empty
            if (indices == -1).all():
                dtype = np.result_type(self.sp_values, type(fill_value))
                taken = np.empty_like(indices, dtype=dtype)
                taken.fill(fill_value)
                return taken
            else:
                raise IndexError("cannot do a non-empty take from an empty axes.")

        # sp_indexer may be -1 for two reasons
        # 1.) we took for an index of -1 (new)
        # 2.) we took a value that was self.fill_value (old)
        sp_indexer = self.sp_index.lookup_array(indices)
        new_fill_indices = indices == -1
        old_fill_indices = (sp_indexer == -1) & ~new_fill_indices

View on GitHub (pinned to 3b7651241d)

Solutions

  1. Bound-check: indices = indices[(indices >= -1) & (indices < len(arr))].
  2. Use pd.Series(arr).reindex(labels) for label-based reindex instead of manual take.
  3. Drop allow_fill and let negative/positive positions wrap, after confirming they are in range.

Example fix

// before
arr.take([0, len(arr)], allow_fill=True)  # raises
// after
import numpy as np
idx = np.array([0, len(arr)-1])
arr.take(idx, allow_fill=True)
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np
def bounded_indices(arr, indices):
    idx = np.asarray(indices)
    return idx[(idx >= -1) & (idx < len(arr))]

Type guard

def indices_in_range(arr, indices) -> bool:
    import numpy as np
    idx = np.asarray(indices)
    return bool(idx.max() < len(arr) and idx.min() >= -1)

Try / catch

try:
    arr.take(indices, allow_fill=True)
except IndexError as e:
    if 'out of bounds' in str(e):
        out = arr.take(bounded_indices(arr, indices), allow_fill=True)
    else:
        raise

Prevention

When it happens

Trigger: arr.take([0, len(arr)], allow_fill=True); forwarding computed indices without bounding to the array length.

Common situations: Reindexing logic that produces positions equal to the array length; using a positional array from a longer array on a shorter one.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/f6f49f56858ebec4. Report an issue: GitHub.