pandas-dev/pandas · error · ValueError

name_or_index must be an int, str, bytes…

Error message

name_or_index must be an int, str, bytes, pyarrow.compute.Expression, or list of those

What it means

`ValueError('name_or_index must be an int, str, bytes, pyarrow.compute.Expression, or list of those')` from the inner `get_name` of `StructAccessor.field`. The accepted shapes are: int field index, str/bytes field name, a `pyarrow.compute.Expression` (e.g. `pc.field('x')`), or a list of those for nested struct traversal. Any other type (dict, tuple, numpy scalar, None) lands in the `else`.

Solutions

  1. Pass a field name: `s.struct.field('a')`.
  2. Pass a positional int: `s.struct.field(0)`.
  3. For nested access use a list of those: `s.struct.field(['version', 'minor'])`.
  4. For Expression form use `pyarrow.compute.field('a')`.

Example fix

// before
s.struct.field({'name': 'a'})   # dict -> ValueError
s.struct.field(None)            # -> ValueError

// after
s.struct.field('a')
s.struct.field(['version', 'minor'])
Defensive patterns

Strategy: type-guard

Validate before calling

import pyarrow.compute as pc
from pandas.api.types import is_list_like
if not isinstance(name_or_index, (int, str, bytes, pc.Expression)) and not is_list_like(name_or_index):
    raise TypeError('name_or_index must be int, str, bytes, pc.Expression, or list of those')
s.struct.field(name_or_index)

Type guard

def is_valid_struct_field_key(key) -> bool:
    import pyarrow.compute as pc
    from pandas.api.types import is_list_like
    return isinstance(key, (int, str, bytes, pc.Expression)) or is_list_like(key)

Try / catch

try:
    out = s.struct.field(name_or_index)
except ValueError as e:
    if 'name_or_index must be' in str(e):
        raise TypeError('Pass a field name (str), index (int), or list for nested access') from e
    raise

Prevention

When it happens

Trigger: `s.struct.field({'a': 1})`, `s.struct.field(None)`, `s.struct.field((0,1))` (tuple instead of list — note only `is_list_like` is allowed, which does include tuples... actually `is_list_like` returns True for tuples, so the real trigger is non-list-like types: scalars of wrong dtype, dict, None, custom objects).

Common situations: Passing a dict (mistaking the API for a constructor); passing None; passing a numpy array of names; passing a custom object whose type is neither str/bytes/int/Expression nor list-like.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/b85a6bd6e44b84c6. Report an issue: GitHub.

Appendix: 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 3b7651241d)