pandas-dev/pandas · error · ValueError

'indices' must be an array, not a scalar

Error message

'indices' must be an array, not a scalar '{indices}'.

What it means

ValueError from SparseArray.take when the indices argument is a scalar rather than array-like. take requires an iterable of integer positions because it builds a new SparseArray; scalar lookup should use __getitem__.

Solutions

  1. Wrap scalar indices in a list: arr.take([3]).
  2. Use arr[3] directly for single-element access.
  3. Validate: indices = np.atleast_1d(indices) before calling take.

Example fix

// before
arr.take(3)  # raises
// after
arr.take([3])
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np
def take_safe(arr, indices):
    return arr.take(np.atleast_1d(indices))

Type guard

def is_scalar_index(indices) -> bool:
    import numbers
    return isinstance(indices, numbers.Integral)

Try / catch

try:
    arr.take(indices)
except ValueError as e:
    if 'must be an array' in str(e):
        out = arr.take([indices])
    else:
        raise

Prevention

When it happens

Trigger: arr.take(3) (scalar) instead of arr.take([3]); passing a python int where an array/list is expected.

Common situations: Generic code calling take with whatever value a caller supplied without wrapping; refactoring from arr[i] to .take.

Related errors


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

Appendix: source

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

        if loc < 0:
            loc += n

        if loc >= n or loc < 0:
            raise IndexError(
                f"index is out of bounds: must be an integer between -{n} and {n - 1}"
            )

        sp_loc = self.sp_index.lookup(loc)
        if sp_loc == -1:
            return self.fill_value
        else:
            val = self.sp_values[sp_loc]
            val = maybe_box_datetimelike(val, self.sp_values.dtype)
            return val

    def take(self, indices, *, allow_fill: bool = False, fill_value=None) -> Self:
        if is_scalar(indices):
            raise ValueError(f"'indices' must be an array, not a scalar '{indices}'.")
        indices = np.asarray(indices, dtype=np.int32)

        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

View on GitHub (pinned to 3b7651241d)