pandas-dev/pandas · error · IndexError
only integers, slices (`:`), ellipsis (`...`), numpy.newaxis
Error message
only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices
What it means
Raised by ArrowExtensionArray.__getitem__ when the indexer is scalar but not an integer (e.g. a string label, a float like 2.5). The guard at line 905 explicitly checks `is_scalar(item) and not is_integer(item)` and raises with a numpy-style message. Positional indexing on ArrowExtensionArray requires integer positions; label-based access must go through .loc.
Source
Thrown at pandas/core/arrays/arrow/array.py:908
return self.take(item)
elif item.dtype.kind == "b":
return self._from_pyarrow_array(self._pa_array.filter(item))
else:
raise IndexError(
"Only integers, slices and integer or "
"boolean arrays are valid indices."
)
elif isinstance(item, tuple):
item = unpack_tuple_and_ellipses(item)
if item is Ellipsis:
# TODO: should be handled by pyarrow?
item = slice(None)
if is_scalar(item) and not is_integer(item):
# e.g. "foo" or 2.5
# exception message copied from numpy
raise IndexError(
r"only integers, slices (`:`), ellipsis (`...`), numpy.newaxis "
r"(`None`) and integer or boolean arrays are valid indices"
)
# We are not an array indexer, so maybe e.g. a slice or integer
# indexer. We dispatch to pyarrow.
value = self._pa_array[item]
if isinstance(value, pa.ChunkedArray):
result = self._from_pyarrow_array(value)
if getitem_returns_view(self, item):
result._readonly = self._readonly
return result
else:
pa_type = self._pa_array.type
scalar = value.as_py()
if scalar is None:
return self._dtype.na_value
elif pa.types.is_timestamp(pa_type) and pa_type.unit != "ns":
# GH 53326View on GitHub (pinned to 71959b8cb9)
Solutions
- Use an explicit int: s_arr[int(idx)].
- For label access go through the Series: series.loc['a'].
- Validate indices: int_idx = operator.index(idx) before indexing.
- If idx is a numpy scalar, cast: s_arr[int(idx.item())].
Example fix
# before val = arrow_arr['field_a'] # IndexError: scalar non-int val = arrow_arr[2.0] # IndexError # after val = series.loc['field_a'] # label access val = arrow_arr[int(2.0)] # positional int
Defensive patterns
Strategy: validation
Validate before calling
import operator
def safe_scalar_get(arr, item):
if isinstance(item, str):
raise IndexError('use Series.loc for label access')
try:
item = operator.index(item)
except TypeError as e:
raise IndexError(f'non-integer scalar index {item!r}') from e
return arr[item]
val = safe_scalar_get(arrow_arr, idx) Type guard
import numbers
def is_integer_scalar_index(x) -> bool:
return isinstance(x, numbers.Integral) and not isinstance(x, bool) Try / catch
try:
val = arrow_arr[key]
except IndexError as e:
if 'only integers' in str(e):
# route label access through Series
val = pd.Series(arrow_arr).loc[key]
else:
raise Prevention
- Distinguish label access (.loc) from positional access (.iloc/int) explicitly.
- Use operator.index(x) to validate/coerce integer positions.
- Avoid floats as positional indices; cast to int.
When it happens
Trigger: Indexing positionally with a label: `s_arr['a']` on an ArrowExtensionArray, or `s_arr[2.0]`. Floating scalar indices. Also passing an Ellipsis-wrapped tuple that collapses to a non-int scalar.
Common situations: Treating an ExtensionArray like a Series (which supports label indexing), or assuming integer-valued floats round. Common when migrating numpy-backed code where `arr[2.0]` silently truncated to `arr[2]`.
Related errors
- key must be an int or slice, got {type(key).__name__}
- name_or_index must be an int, str, bytes, pyarrow.compute.Ex
- Only integers, slices and integer or boolean arrays are vali
- 'indices' must be an array, not a scalar '{indices}'.
- Invalid side: {side}. Side must be one of 'left', 'right', '
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/55f69b74812de448.
Report an issue: GitHub.