pandas-dev/pandas · error · AttributeError
Can only use .cat accessor with a 'category' dtype
Error message
Can only use .cat accessor with a 'category' dtype
What it means
Raised by CategoricalAccessor._validate when the .cat accessor is invoked on a Series whose dtype is not CategoricalDtype. The accessor is registered only for category dtype; accessing .cat on any other dtype triggers this AttributeError. It is the standard pandas 'wrong accessor for dtype' guard.
Source
Thrown at pandas/core/arrays/categorical.py:3067
2 b
3 c
4 c
5 c
dtype: category
Categories (3, str): ['a', 'b', 'c']
"""
def __init__(self, data) -> None:
self._validate(data)
self._parent = data.values
self._index = data.index
self._name = data.name
self._freeze()
@staticmethod
def _validate(data) -> None:
if not isinstance(data.dtype, CategoricalDtype):
raise AttributeError("Can only use .cat accessor with a 'category' dtype")
def _delegate_property_get(self, name: str):
return getattr(self._parent, name)
def _delegate_property_set(self, name: str, new_values) -> None:
setattr(self._parent, name, new_values)
@property
def codes(self) -> Series:
"""
Return Series of codes as well as the index.
The codes are integer indicators for the position of each value in
the categories. Uncategorized values (i.e., NaN) are assigned a code
of ``-1``.
See Also
--------View on GitHub (pinned to 71959b8cb9)
Solutions
- Convert the Series to category first: s = s.astype('category').
- Check dtype before accessing .cat: if isinstance(s.dtype, pd.CategoricalDtype): ...
- Investigate upstream operations (merge, concat, astype) that may have stripped the category dtype.
Example fix
// before
s = pd.Series(['a','b','a'])
s.cat.categories # AttributeError: Can only use .cat accessor with a 'category' dtype
// after
s = s.astype('category')
s.cat.categories Defensive patterns
Strategy: type-guard
Validate before calling
def require_category(s):
import pandas as pd
if not isinstance(s.dtype, pd.CategoricalDtype):
s = s.astype('category')
return s Type guard
import pandas as pd
from typing import Any
def is_category_dtype(obj: Any) -> bool:
return isinstance(getattr(obj, 'dtype', None), pd.CategoricalDtype) Try / catch
try:
s.cat.categories
except AttributeError as e:
if 'category' in str(e) and 'accessor' in str(e):
s = s.astype('category')
else:
raise Prevention
- Always call .astype('category') before using .cat.
- Re-check dtype after merge/concat that may strip category type.
When it happens
Trigger: s.cat.categories / s.cat.ordered / s.cat.codes on a Series that is object, int, str, or datetime dtype instead of category. Common after the Series dtype is reset by an operation that drops the category type.
Common situations: After .astype('str') or .to_numpy()-roundtrip that loses category dtype; after merge/join that may coerce category to object; or accessing .cat before converting with astype('category').
Related errors
- You cannot access the property {name}
- You cannot call method {name}
- codes need to be array-like integers
- Object with dtype {self.dtype} cannot perform the numpy op {
- category, object, and string subtypes are not supported for
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/9a1e4f6fbbf3808d.
Report an issue: GitHub.