pandas-dev/pandas · error · IndexError

cannot do a non-empty take

Error message

cannot do a non-empty take

What it means

Raised by ExtensionArray.take when the source array is empty (length 0) but the requested indices contain at least one non-negative value. Taking elements from an empty array is logically impossible, so pandas rejects it as an IndexError.

Source

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

            When `indices` contains negative values other than ``-1``
            and `allow_fill` is True.

        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)))

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Guard for empty input before calling take: `if len(arr) == 0: return arr`.
  2. Check that indices are all negative/sentinel-only when the array is empty (use allow_fill=True with -1 sentinels).
  3. Filter or skip the operation when the source frame has zero rows.

Example fix

// before
arr = pd.array([], dtype="int64[pyarrow]")
arr.take([0])

// after
if len(arr):
    arr.take([0])
else:
    arr  # nothing to take
Defensive patterns

Strategy: validation

Validate before calling

def safe_take(arr, indices, allow_fill=False, fill_value=None):
    if len(arr) == 0:
        return arr
    return arr.take(indices, allow_fill=allow_fill, fill_value=fill_value)

Type guard

def take_is_safe(arr, indices) -> bool:
    import numpy as np
    idx = np.asanyarray(indices)
    return len(arr) > 0 or not bool((idx >= 0).any())

Try / catch

try:
    arr.take(indices)
except IndexError as e:
    if "cannot do a non-empty take" in str(e):
        result = arr  # empty source -> empty result
    else:
        raise

Prevention

When it happens

Trigger: Calling `take(indices, allow_fill=...)` on an empty ArrowExtensionArray where `indices` contains any index >= 0; commonly reached via `Series.reindex`, `.iloc`, or `.take` on an empty Series.

Common situations: Operating on a filtered DataFrame that became empty, reindexing against a target index that no rows match, or generic code that doesn't short-circuit on empty input.

Related errors


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