pandas-dev/pandas · error · ValueError

Invalid value in 'indices'. Must be between -1 and the lengt

Error message

Invalid value in 'indices'. Must be between -1 and the length of the array.

What it means

ValueError from SparseArray._take_with_fill when allow_fill=True and the minimum index is less than -1. With allow_fill, -1 is the only legal sentinel (it means 'use fill_value'); anything smaller is invalid.

Source

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

        dtype = None
        if indices.size == 0:
            result = np.array([], dtype="object")
            dtype = self.dtype
        elif allow_fill:
            result = self._take_with_fill(indices, fill_value=fill_value)
        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

View on GitHub (pinned to 3b7651241d)

Solutions

  1. Clamp negatives: indices = np.where(indices < -1, -1, indices) if you want fill, or drop allow_fill for true negative indexing.
  2. Use allow_fill=False (default) to use standard negative positions.
  3. Validate indices.min() >= -1 before calling take with allow_fill=True.

Example fix

// before
arr.take([-2, 0], allow_fill=True)  # raises
// after
arr.take([0, 0], allow_fill=True)  # or use allow_fill=False with [-2, 0]
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np
def clamped_fill_indices(indices):
    arr_idx = np.asarray(indices)
    arr_idx[arr_idx < -1] = -1
    return arr_idx

Type guard

def fill_indices_valid(indices) -> bool:
    import numpy as np
    return bool(np.asarray(indices).min() >= -1)

Try / catch

try:
    arr.take(indices, allow_fill=True)
except ValueError as e:
    if 'Must be between -1' in str(e):
        out = arr.take(clamped_fill_indices(indices), allow_fill=True)
    else:
        raise

Prevention

When it happens

Trigger: arr.take([-2, 0, 3], allow_fill=True); computing indices with an off-by-one negative shift and forwarding them.

Common situations: Mixing allow_fill=True semantics (which use -1 as sentinel) with normal negative indexing (which uses -n..-1).

Related errors


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