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
- Guard for empty input before calling take: `if len(arr) == 0: return arr`.
- Check that indices are all negative/sentinel-only when the array is empty (use allow_fill=True with -1 sentinels).
- 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
- Short-circuit take/reindex on empty inputs.
- In ETL pipelines, guard `if len(df) == 0: return df` before positional slicing.
- Use allow_fill=True when missing positions are expected.
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
- out of bounds value in 'indices'.
- index {key} is out of bounds for axis 0 with size {n}
- Length of indexer and values mismatch
- 'indices' must be an array, not a scalar '{indices}'.
- pd.api.extensions.take requires a numpy.ndarray, ExtensionAr
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/4c59940c4ed35bb2.
Report an issue: GitHub.