pandas-dev/pandas · error · ValueError

Lengths must match.

Error message

Lengths must match.

What it means

Raised inside the comparison operator built by `_cat_compare_op` when `other` is a list-like whose length differs from the Categorical and `other` is not hashable. Pandas requires element-wise comparisons against list-likes to be broadcastable (equal length). The hashable carve-out exists so a single tuple that is itself a category is treated as a scalar, not a sequence.

Solutions

  1. Verify `len(other) == len(cat)` before comparing; align or filter the list-like to match.
  2. If you meant scalar comparison, pass the scalar directly (not wrapped in a list/tuple).
  3. For index-aligned comparison, wrap both sides in a Series first: `pd.Series(cat) == pd.Series(other)`.
  4. If comparing against a single tuple-as-category, ensure the tuple is itself hashable and present in `cat.categories`.

Example fix

# before
import pandas as pd
cat = pd.Categorical(['a', 'b', 'c'])
result = cat == ['a', 'b']  # ValueError: Lengths must match.

# after (scalar)
result = cat == 'a'
# after (aligned list-like)
result = cat == ['a', 'b', 'c']
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np
from pandas.api.types import is_list_like

def safe_cat_compare(cat, other):
    if is_list_like(other) and len(other) != len(cat):
        raise ValueError(f"length {len(other)} != {len(cat)}; align before compare")
    return cat == other

Type guard

from pandas.api.types import is_list_like, is_hashable

def is_broadcastable_to(cat, other) -> bool:
    if not is_list_like(other) or is_hashable(other):
        return True
    return len(other) == len(cat)

Try / catch

try:
    result = cat == other
except ValueError as e:
    if "Lengths must match" in str(e):
        # align lengths, then retry
        ...
    raise

Prevention

When it happens

Trigger: Calling any comparison operator (`==`, `!=`, `<`, `>`, `<=`, `>=`) on a Categorical with a Python list, numpy array, Series, or Index whose `len()` differs from `len(cat)` — e.g. `pd.Categorical(['a','b','c']) == ['a','b']`.

Common situations: Mismatched index alignment expectations (users assume pandas auto-aligns like Series does — it does not for raw Categorical ops), broadcasting a scalar accidentally wrapped in a list, or feeding a column from a differently-filtered DataFrame.

Related errors


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

Appendix: source

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

    )

    from pandas import (
        DataFrame,
        Index,
        Series,
    )


def _cat_compare_op(op):
    opname = f"__{op.__name__}__"
    fill_value = op is operator.ne

    @unpack_zerodim_and_defer(opname)
    def func(self, other):
        hashable = is_hashable(other)
        if is_list_like(other) and len(other) != len(self) and not hashable:
            # in hashable case we may have a tuple that is itself a category
            raise ValueError("Lengths must match.")

        if not self.ordered:
            if opname in ["__lt__", "__gt__", "__le__", "__ge__"]:
                raise TypeError(
                    "Unordered Categoricals can only compare equality or not"
                )
        if isinstance(other, Categorical):
            # Two Categoricals can only be compared if the categories are
            # the same (maybe up to ordering, depending on ordered)

            msg = "Categoricals can only be compared if 'categories' are the same."
            if not self._categories_match_up_to_permutation(other):
                raise TypeError(msg)

            if not self.ordered and not self.categories.equals(other.categories):
                # both unordered and different order
                other_codes = recode_for_categories(
                    other.codes, other.categories, self.categories, copy=False

View on GitHub (pinned to 3b7651241d)