pandas-dev/pandas · error · IndexError

out of bounds value in 'indices'.

Error message

out of bounds value in 'indices'.

What it means

The second guard in take(): after the empty-array check, if the largest requested index exceeds (or equals) the length of self._pa_array, the position is out of range. validate_indices is called only inside the allow_fill branch, so this explicit check protects the non-fill path.

Solutions

  1. Clip or recompute indices against the current array length: indices = indices[indices < len(arr)].
  2. Switch to allow_fill=True with negative sentinel indices and a fill_value for out-of-range positions.
  3. Re-derive indices after any filter/sort that changes the array length.

Example fix

// before
arr = pd.array([1, 2, 3], dtype="int64[pyarrow]")
arr.take([5])
// after
arr = pd.array([1, 2, 3], dtype="int64[pyarrow]")
arr.take([5], allow_fill=True, fill_value=-1)
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np

def safe_take(arr, indices):
    idx = np.asanyarray(indices)
    if idx.size and idx.max() >= len(arr):
        raise IndexError("requested index exceeds array length")
    return arr.take(indices)

Type guard

import numpy as np

def indices_in_bounds(arr, indices) -> bool:
    idx = np.asanyarray(indices)
    return idx.size == 0 or idx.max() < len(arr)

Try / catch

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

Prevention

When it happens

Trigger: Calling .take([n]) or fancy indexing where an index >= len(arr) on a pyarrow-backed ExtensionArray, e.g. pd.array([1,2], dtype='int64[pyarrow]').take([5]).

Common situations: Off-by-one bugs in computed indices; reusing indices from a larger frame on a filtered subset; iloc with stale positions after row removal.

Related errors


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

Appendix: source

Thrown at pandas/core/arrays/arrow/array.py:2093

        See Also
        --------
        numpy.take
        api.extensions.take

        Notes
        -----
        ExtensionArray.take is called by ``Series.__getitem__``, ``.loc``,
        ``iloc``, when `indices` is a sequence of values. Additionally,
        it's called by :meth:`Series.reindex`, or any other method
        that causes realignment, with a `fill_value`.
        """
        indices_array = np.asanyarray(indices)

        if len(self._pa_array) == 0 and (indices_array >= 0).any():
            raise IndexError("cannot do a non-empty take")
        if indices_array.size > 0 and indices_array.max() >= len(self._pa_array):
            raise IndexError("out of bounds value in 'indices'.")

        if allow_fill:
            fill_mask = indices_array < 0
            if fill_mask.any():
                validate_indices(indices_array, len(self._pa_array))
                # TODO(ARROW-9433): Treat negative indices as NULL
                indices_array = pa.array(indices_array, mask=fill_mask)
                result = self._pa_array.take(indices_array)
                if isna(fill_value):
                    return self._from_pyarrow_array(result)
                # TODO: ArrowNotImplementedError: Function fill_null has no
                # kernel matching input types (array[string], scalar[string])
                result = self._from_pyarrow_array(result)
                result[fill_mask] = fill_value
                return result
                # return type(self)(pc.fill_null(result, pa.scalar(fill_value)))
            else:
                # Nothing to fill

View on GitHub (pinned to 3b7651241d)