pandas-dev/pandas · error · TypeError

Cannot compare {conv_val} of type {type(conv_val)} to {kind}

Error message

Cannot compare {conv_val} of type {type(conv_val)} to {kind} column

What it means

Raised by BinOp.convert_value in pandas.core.computation.pytables when the right-hand comparison value cannot be coerced to the column's kind. The function handles datetime, timedelta, category, integer, float, bool, and string columns; anything else (e.g. a list, dict, complex, bytes, or an object that is not a str) falls through to the final TypeError. The {kind} placeholder shows what the column actually is, and {type(conv_val)} shows the offending Python type.

Source

Thrown at pandas/core/computation/pytables.py:307

                conv_val = conv_val.strip().lower() not in [
                    "false",
                    "f",
                    "no",
                    "n",
                    "none",
                    "0",
                    "[]",
                    "{}",
                    "",
                ]
            else:
                conv_val = bool(conv_val)
            return TermValue(conv_val, conv_val, kind)
        elif isinstance(conv_val, str):
            # string quoting
            return TermValue(conv_val, stringify(conv_val), "string")
        else:
            raise TypeError(
                f"Cannot compare {conv_val} of type {type(conv_val)} to {kind} column"
            )

    def convert_values(self) -> None:
        pass


class FilterBinOp(BinOp):
    filter: tuple[Any, Any, Index] | None = None

    def __repr__(self) -> str:
        if self.filter is None:
            return "Filter: Not Initialized"
        return pprint_thing(f"[Filter : [{self.filter[0]}] -> [{self.filter[1]}]")

    def invert(self) -> Self:
        """invert the filter"""
        if self.filter is not None:

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Match the literal type to the column kind: use plain Python int/float/str/bool, or a pandas.Timestamp for datetime columns.
  2. For membership (multiple values), use the 'in'/'==' with a list literal that the FilterBinOp path handles: where='col == [1,2,3]' only when col is a data_column.
  3. Cast the value before passing: int(v), float(v), str(v), or pd.Timestamp(v) for datetimes.
  4. If the value can be None, handle NaN explicitly (e.g. store with nullable dtype and query 'col != col' for NaN).

Example fix

# before
store.select('df', where='amount == 1.5j')  # TypeError: Cannot compare 1.5j of type complex to float column

# after (cast to the column's kind)
store.select('df', where='amount == 1.5')   # float column -> float literal
# for datetime columns:
store.select('df', where="ts == Timestamp('2020-01-01')")
Defensive patterns

Strategy: type-guard

Validate before calling

import numpy as np

def coerce_query_value(value, kind):
    if kind in ('integer',):
        return int(value)
    if kind in ('float',):
        return float(value)
    if kind in ('bool',):
        return bool(value)
    if kind in ('datetime',) or (kind or '').startswith('datetime64'):
        import pandas as pd
        return pd.Timestamp(value)
    if isinstance(value, str):
        return value
    raise TypeError(f'cannot coerce {value!r} for kind {kind!r}')

Type guard

import numpy as np

def is_comparable_scalar(v) -> bool:
    return isinstance(v, (int, float, bool, str, np.integer, np.floating, np.bool_))

Try / catch

try:
    store.select('df', where=f'col == {value!r}')
except TypeError as e:
    if 'Cannot compare' in str(e):
        # cast value to the column's kind and retry
        value = coerce_query_value(value, kind)
        store.select('df', where=f'col == {value!r}')
    raise

Prevention

When it happens

Trigger: store.select('df', where='cat_col == [1,2]') (list vs single value handling edge); comparing an integer column to a Python complex or bytes object; passing a None to a non-nullable column kind; comparing a string column to a non-str object.

Common situations: Programmatic where-clause construction where the comparison value comes from untrusted/dynamic input; mismatched dtypes between the stored column and the query literal; passing numpy scalars of unusual dtypes (e.g. np.complex128).

Related errors


AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07). Data as JSON: /api/errors/e11d465727a1b13c. Report an issue: GitHub.