pandas-dev/pandas · error · ValueError
key must be an int or slice, got
Error message
key must be an int or slice, got {type(key).__name__} What it means
`ValueError('key must be an int or slice, got {type}')` from `ListAccessor.__getitem__`. The accessor only accepts an `int` (positional list index, forwarded to `pc.list_element`) or a `slice` (forwarded to `pc.list_slice`). Anything else — a string field name, a list of indices, a numpy array, a tuple — falls through to the `else` and raises. Note negative int is not yet supported (pyarrow limitation called out in the code).
Solutions
- Use an int for a single position: `s.list[0]`.
- Use a slice for a sub-range: `s.list[0:2]`.
- For per-row variable indices, build an integer pyarrow array and use `pc.list_element` directly, or `explode`+filter.
- If you meant a named field, switch to `.struct.field(name)` on a struct-dtype Series.
Example fix
// before s.list[[0, 1]] # list key -> ValueError s.list['first'] # str key -> ValueError // after s.list[0:2] # slice # per-row indices: idx = pa.array([0,1,0]) pd.Series(pa.compute.list_element(s.array._pa_array, idx), index=s.index)
Defensive patterns
Strategy: type-guard
Validate before calling
if not isinstance(key, (int, slice)):
raise TypeError(f'list accessor key must be int or slice, got {type(key).__name__}')
s.list[key] Type guard
def is_valid_list_key(key) -> bool:
return isinstance(key, (int, slice)) and not (isinstance(key, int) and key < 0) Try / catch
try:
out = s.list[key]
except ValueError as e:
if 'key must be an int or slice' in str(e):
raise TypeError('Use .list[int] or .list[slice]; for names use .struct.field') from e
raise Prevention
- Remember .list indexes positions only (int/slice); .struct.field indexes names
- Avoid negative ints - not yet supported
When it happens
Trigger: `s.list['name']` (string), `s.list[[0,1]]` (list), `s.list[1:3:2]` works but `s.list[-1]` is unsupported, `s.list[arr]` (numpy array), `s.list[(0,1)]` (tuple).
Common situations: Confusing the list accessor with the struct accessor (`.list` indexes positions, `.struct.field` indexes names); trying fancy indexing; assuming negative indexing works as it does on Python lists.
Related errors
- Can only use the '.list' accessor with 'list[pyarrow]'…
- ' ' object is not iterable
- Can only use the '.struct' accessor with 'struct[pyarrow]'…
- name_or_index must be an int, str, bytes…
- ambiguous is not supported.
AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11).
Data as JSON: /api/errors/393610b54f743394.
Report an issue: GitHub.
Appendix: source
Thrown at pandas/core/arrays/arrow/accessors.py:195
# TODO: Support negative start/stop/step, ideally this would be added
# upstream in pyarrow.
start, stop, step = key.start, key.stop, key.step
if start is None:
# TODO: When adding negative step support
# this should be set to last element of array
# when step is negative.
start = 0
if step is None:
step = 1
sliced = pc.list_slice(self._pa_array, start, stop, step)
return Series(
sliced,
dtype=ArrowDtype(sliced.type),
index=self._data.index,
name=self._data.name,
)
else:
raise ValueError(f"key must be an int or slice, got {type(key).__name__}")
def __iter__(self) -> Iterator:
raise TypeError(f"'{type(self).__name__}' object is not iterable")
def flatten(self) -> Series:
"""
Flatten list values.
Each list element is expanded into separate rows, preserving the
original index. The resulting Series may have a longer length than
the original if lists contain more than one element.
Returns
-------
pandas.Series
The data from all lists in the series flattened.
See AlsoView on GitHub (pinned to 3b7651241d)