pandas-dev/pandas · error · ValueError
name_or_index must be an int, str, bytes, pyarrow.compute.Ex
Error message
name_or_index must be an int, str, bytes, pyarrow.compute.Expression, or list of those
What it means
Thrown by StructAccessor.field (pandas Series.struct.field) when the field selector is not one of the accepted types. The inner get_name helper validates the selector against int, str, bytes, a pyarrow.compute.Expression, or a list-like of those used to drill into nested structs. Anything else (e.g. a float, tuple, dict, None) hits the final else branch and raises. It is a strict input-validation guard before calling pc.struct_field.
Source
Thrown at pandas/core/arrays/arrow/accessors.py:463
name = level_name_or_index
elif isinstance(level_name_or_index, pc.Expression):
name = str(level_name_or_index)
elif is_list_like(level_name_or_index):
# For nested input like [2, 1, 2]
# iteratively get the struct and field name. The last
# one is used for the name of the index.
level_name_or_index = list(reversed(level_name_or_index))
selected = data
while level_name_or_index:
# we need the cast, otherwise mypy complains about
# getting ints, bytes, or str here, which isn't possible.
level_name_or_index = cast("list", level_name_or_index)
name_or_index = level_name_or_index.pop()
name = get_name(name_or_index, selected)
selected = selected.type.field(selected.type.get_field_index(name))
name = selected.name
else:
raise ValueError(
"name_or_index must be an int, str, bytes, "
"pyarrow.compute.Expression, or list of those"
)
return name
pa_arr = self._data.array._pa_array
name = get_name(name_or_index, pa_arr)
field_arr = pc.struct_field(pa_arr, name_or_index)
return Series(
field_arr,
dtype=ArrowDtype(field_arr.type),
index=self._data.index,
name=name,
)
def explode(self) -> DataFrame:
"""View on GitHub (pinned to 71959b8cb9)
Solutions
- Coerce numeric selectors to int before calling: s.struct.field(int(field_idx)).
- Pass the struct field name as a str: s.struct.field('my_field').
- For nested struct access, pass a list of int/str such as s.struct.field([0, 'child']).
- If building a pyarrow expression, pass pc.struct_field(...) style Expression objects directly.
Example fix
# before
idx = payload['field'] # may be 2.5 or None from JSON
s.struct.field(idx)
# after
idx = payload['field']
assert isinstance(idx, (int, str, bytes)), f'bad field selector {idx!r}'
s.struct.field(int(idx) if isinstance(idx, (int, float)) and float(idx).is_integer() else idx) Defensive patterns
Strategy: validation
Validate before calling
import pyarrow.compute as pc
def valid_struct_field(x):
return (
isinstance(x, (int, str, bytes))
or isinstance(x, pc.Expression)
or (hasattr(x, '__iter__') and all(isinstance(i, (int, str, bytes, pc.Expression)) for i in x))
)
# before: s.struct.field(selector)
assert valid_struct_field(selector), f'invalid field selector {selector!r}'
s.struct.field(selector) Type guard
from typing import Union, List
import pyarrow.compute as pc
StructFieldSelector = Union[int, str, bytes, pc.Expression, List[Union[int, str, bytes, pc.Expression]]]
def is_struct_field_selector(x) -> bool:
if isinstance(x, (int, str, bytes, pc.Expression)):
return True
if hasattr(x, '__iter__') and not isinstance(x, (str, bytes)):
return all(isinstance(i, (int, str, bytes, pc.Expression)) for i in x)
return False Try / catch
try:
col = s.struct.field(selector)
except ValueError as e:
if 'name_or_index must be' in str(e):
raise ValueError(f'Bad struct field selector {selector!r}; expected int/str/bytes/Expression/list') from e
raise Prevention
- Always normalize numeric field selectors to int before passing.
- Validate user-supplied field selectors against the accepted type tuple.
- Prefer field names (str) over indices for readability and schema robustness.
When it happens
Trigger: Calling `s.struct.field(<X>)` where <X> is not int/str/bytes/pyarrow Expression/list. Examples: `s.struct.field(2.5)`, `s.struct.field(None)`, `s.struct.field(('a','b'))` where tuple is rejected by is_list_like path, or passing a pyarrow Type object instead of a field name/index.
Common situations: Dynamically building the field selector from user input or config and passing a float index (e.g. JSON-parsed number), passing None as a 'no-op' field, or confusing the struct field name with a column expression object. Common when reading nested schemas and indexing by a value that came in as a non-int numeric.
Related errors
- Can only use the '.struct' accessor with 'struct[pyarrow]' d
- key must be an int or slice, got {type(key).__name__}
- Only integers, slices and integer or boolean arrays are vali
- only integers, slices (`:`), ellipsis (`...`), numpy.newaxis
- invalid na_position: {na_position}
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/b85a6bd6e44b84c6.
Report an issue: GitHub.