pandas-dev/pandas · error · TypeError

'values' is not ordered, please explicitly specify the…

Error message

'values' is not ordered, please explicitly specify the categories order by passing in a categories argument.

What it means

Raised during category inference in `__init__` when `dtype.ordered=True` but `factorize(values, sort=True)` raised `TypeError` (the values are not sortable, e.g. mixed incompatible types) and the fallback `factorize(sort=False)` succeeded. Because an ordered categorical requires a well-defined sort order, pandas asks the caller to supply an explicit `categories` sequence defining that order.

Solutions

  1. Provide an explicit ordered category list: `pd.Categorical(values, categories=[...], ordered=True)`.
  2. Clean/coerce the values to a single sortable dtype before construction.
  3. Drop `ordered=True` if a total order is not actually required.
  4. Pre-sort the unique values yourself and pass them as `categories`.

Example fix

# before
import pandas as pd
cat = pd.Categorical(['a', 1, 'b'], ordered=True)  # TypeError

# after
cat = pd.Categorical(
    ['a', 1, 'b'],
    categories=['a', 'b', 1],  # explicit order
    ordered=True,
)
Defensive patterns

Strategy: validation

Validate before calling

def ordered_categorical(values, categories=None):
    if categories is None:
        import pandas as pd
        uniq = pd.unique([v for v in values if v is not None])
        try:
            uniq = sorted(uniq)
        except TypeError as e:
            raise TypeError(
                'values are not sortable; pass categories= explicitly'
            ) from e
        categories = uniq
    return pd.Categorical(values, categories=categories, ordered=True)

Type guard

def is_sortable(values) -> bool:
    try:
        sorted(values)
        return True
    except TypeError:
        return False

Try / catch

try:
    cat = pd.Categorical(values, ordered=True)
except TypeError as e:
    if 'is not ordered' in str(e):
        cat = pd.Categorical(values, categories=sorted(set(values)), ordered=True)
    else:
        raise

Prevention

When it happens

Trigger: Constructing `pd.Categorical(values, ordered=True)` where `values` contains heterogeneous/unorderable types (e.g. `['a', 1, None]`), or unorderable objects whose `__lt__` raises.

Common situations: Loading messy CSV columns with mixed dtypes; building ordered categoricals from object columns that contain a few stray numeric/None entries; user-defined classes without a total order.

Related errors


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

Appendix: source

Thrown at pandas/core/arrays/categorical.py:485

                categories = arr.dictionary.to_pandas(types_mapper=ArrowDtype)
                codes = arr.indices.to_numpy()
                dtype = CategoricalDtype(categories, values.dtype.pyarrow_dtype.ordered)
            else:
                preserve_object = False
                if isinstance(values, (ABCIndex, ABCSeries)) and values.dtype == object:
                    # GH#61778
                    preserve_object = True
                if not isinstance(values, ABCIndex):
                    # in particular RangeIndex xref test_index_equal_range_categories
                    values = sanitize_array(values, None)
                try:
                    codes, categories = factorize(values, sort=True)
                except TypeError as err:
                    codes, categories = factorize(values, sort=False)
                    if dtype.ordered:
                        # raise, as we don't have a sortable data structure and so
                        # the user should give us one by specifying categories
                        raise TypeError(
                            "'values' is not ordered, please "
                            "explicitly specify the categories order "
                            "by passing in a categories argument."
                        ) from err

                if preserve_object:
                    # GH#61778 wrap categories in an Index to prevent dtype
                    #  inference in the CategoricalDtype constructor
                    from pandas import Index

                    categories = Index(categories, dtype=object, copy=False)

                # if not preserve_object, we're inferring from values
                dtype = CategoricalDtype(categories, dtype.ordered)

        elif isinstance(values.dtype, CategoricalDtype):
            old_codes = extract_array(values)._codes
            codes = recode_for_categories(

View on GitHub (pinned to 3b7651241d)