pandas-dev/pandas · error · ValueError
The categories must be provided in 'categories' or 'dtype'.
Error message
The categories must be provided in 'categories' or 'dtype'. Both were None.
What it means
Raised by Categorical.from_codes when neither `categories` nor a `dtype` (CategoricalDtype) carrying categories is supplied. from_codes constructs a categorical directly from integer codes, so it cannot infer categories from data; the categories must be provided explicitly to give the codes meaning.
Source
Thrown at pandas/core/arrays/categorical.py:796
codes : The category codes of the categorical.
CategoricalIndex : An Index with an underlying ``Categorical``.
Examples
--------
>>> dtype = pd.CategoricalDtype(["a", "b"], ordered=True)
>>> pd.Categorical.from_codes(codes=[0, 1, 0, 1], dtype=dtype)
['a', 'b', 'a', 'b']
Categories (2, str): ['a' < 'b']
"""
dtype = CategoricalDtype._from_values_or_dtype(
categories=categories, ordered=ordered, dtype=dtype
)
if dtype.categories is None:
msg = (
"The categories must be provided in 'categories' or "
"'dtype'. Both were None."
)
raise ValueError(msg)
if validate:
# beware: non-valid codes may segfault
codes = cls._validate_codes_for_dtype(codes, dtype=dtype)
return cls._simple_new(codes, dtype=dtype)
# ------------------------------------------------------------------
# Categories/Codes/Ordered
@property
def categories(self) -> Index:
"""
The categories of this categorical.
Setting assigns new values to each category (effectively a rename of
each individual category).
View on GitHub (pinned to 71959b8cb9)
Solutions
- Pass categories: `pd.Categorical.from_codes([0,1,0], categories=['a','b'])`.
- Pass a CategoricalDtype: `pd.Categorical.from_codes([0,1,0], dtype=pd.CategoricalDtype(['a','b']))`.
- If categories are unknown, use the normal constructor `pd.Categorical(values)` instead of from_codes.
Example fix
# before pd.Categorical.from_codes([0, 1, 0]) # after pd.Categorical.from_codes([0, 1, 0], categories=['a', 'b'])
Defensive patterns
Strategy: validation
Validate before calling
def from_codes_safe(codes, categories=None, dtype=None):
import pandas as pd
if categories is None and (dtype is None or getattr(dtype, 'categories', None) is None):
raise ValueError("supply categories= or a CategoricalDtype")
return pd.Categorical.from_codes(codes, categories=categories, dtype=dtype) Type guard
def has_categories(categories, dtype) -> bool:
import pandas as pd
return categories is not None or (isinstance(dtype, pd.CategoricalDtype) and dtype.categories is not None) Try / catch
try:
cat = pd.Categorical.from_codes(codes)
except ValueError as e:
if "categories" in str(e):
cat = pd.Categorical.from_codes(codes, categories=inferred_categories)
else:
raise Prevention
- Always pass categories with from_codes; persist them alongside codes.
- Consider the regular pd.Categorical(values) constructor when categories are unknown.
- Validate that dtype.categories is not None before calling.
When it happens
Trigger: `pd.Categorical.from_codes([0,1,0])` with no categories= and no dtype=. The _from_values_or_dtype helper returns a dtype with categories=None and from_codes refuses to proceed.
Common situations: Refactoring code that used the regular constructor; copying only the codes array during serialization without persisting the category list.
Related errors
- codes cannot contain NA values
- codes need to be array-like integers
- codes need to be between -1 and len(categories)-1
- Lengths must match.
- Cannot convert float NaN to integer
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/6b5ea518977723c1.
Report an issue: GitHub.