{"record":{"id":"b1ec3e278611f03d","repo":"pandas-dev/pandas","slug":"can-only-use-the-struct-accessor-with-struct-p","errorCode":null,"errorMessage":"Can only use the '.struct' accessor with 'struct[pyarrow]' dtype, not {dtype}.","messagePattern":"Can only use the '\\.struct' accessor with 'struct\\[pyarrow\\]' dtype, not (.+?)\\.","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/arrow/accessors.py","lineNumber":52,"sourceCode":"    @abstractmethod\n    def __init__(self, data, validation_msg: str) -> None:\n        self._data = data\n        self._validation_msg = validation_msg\n        self._validate(data)\n\n    @abstractmethod\n    def _is_valid_pyarrow_dtype(self, pyarrow_dtype) -> bool:\n        pass\n\n    def _validate(self, data) -> None:\n        dtype = data.dtype\n        if not HAS_PYARROW or not isinstance(dtype, ArrowDtype):\n            # Raise AttributeError so that inspect can handle non-struct Series.\n            raise AttributeError(self._validation_msg.format(dtype=dtype))\n\n        if not self._is_valid_pyarrow_dtype(dtype.pyarrow_dtype):\n            # Raise AttributeError so that inspect can handle invalid Series.\n            raise AttributeError(self._validation_msg.format(dtype=dtype))\n\n    @property\n    def _pa_array(self):\n        return self._data.array._pa_array\n\n\nclass ListAccessor(ArrowAccessor):\n    \"\"\"\n    Accessor object for list data properties of the Series values.\n\n    Parameters\n    ----------\n    data : Series\n        Series containing Arrow list data.\n    \"\"\"\n\n    def __init__(self, data=None) -> None:\n        super().__init__(","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/arrow/accessors.py#L34-L70","documentation":"`AttributeError` from `ArrowAccessor._validate` for the `.struct` accessor. It fires when the Series dtype is not an `ArrowDtype` over a pyarrow struct type (`pa.types.is_struct` returns False). Like the `.list` case it uses `AttributeError` so the accessor is hidden from non-struct Series (correct `hasattr` / tab-completion behavior).","triggerScenarios":"`s.struct.field('x')` / `s.struct.explode()` where `s.dtype` is object/dict-of-dict, an Arrow non-struct type (`string[pyarrow]`, `int64[pyarrow]`), or a non-Arrow dtype.","commonSituations":"Loading JSON/parquet into a Series of dicts and forgetting to cast to a struct Arrow dtype; field-access code that assumes pyarrow storage; dtype silently downcast.","solutions":["Construct/convert with an explicit struct dtype: `s.astype(pd.ArrowDtype(pa.struct([(k, pa.int64()) for k in keys])))`.","If loading from records, use `pd.array(records, dtype=pd.ArrowDtype(pa.struct(...)))`.","Guard with `isinstance(s.dtype, pd.ArrowDtype) and pa.types.is_struct(s.dtype.pyarrow_dtype)`."],"exampleFix":"// before\ns = pd.Series([{'a':1},{'a':2}])\ns.struct.field('a')   # object dtype -> AttributeError\n\n// after\nimport pyarrow as pa\ns = pd.Series([{'a':1},{'a':2}], dtype=pd.ArrowDtype(pa.struct([('a', pa.int64())])))\ns.struct.field('a')","handlingStrategy":"type-guard","validationCode":"import pyarrow as pa\nfrom pandas.core.dtypes.dtypes import ArrowDtype\nif not (isinstance(s.dtype, ArrowDtype) and pa.types.is_struct(s.dtype.pyarrow_dtype)):\n    s = s.astype(pd.ArrowDtype(pa.struct([(k, pa.int64()) for k in keys])))\ns.struct.field('a')","typeGuard":"def is_arrow_struct_series(s) -> bool:\n    import pyarrow as pa\n    from pandas.core.dtypes.dtypes import ArrowDtype\n    return isinstance(s.dtype, ArrowDtype) and pa.types.is_struct(s.dtype.pyarrow_dtype)","tryCatchPattern":"try:\n    out = s.struct.field('a')\nexcept AttributeError as e:\n    if '.struct' in str(e):\n        s = s.astype(pd.ArrowDtype(pa.struct([('a', pa.int64')])))\n        out = s.struct.field('a')\n    else:\n        raise","preventionTips":["Cast dict-valued Series to ArrowDtype(pa.struct(...)) before using .struct","Check dtype when loading parquet/JSON into struct Series"],"tags":["accessor","pyarrow","struct","dtype-mismatch"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}