pandas-dev/pandas · error · TypeError

passing a filterable condition to a non-table indexer

Error message

passing a filterable condition to a non-table indexer [{self}]

What it means

Raised in FilterBinOp.evaluate when self.op is not '==' or '!=' and self.is_in_table is False. A FilterBinOp is meant to translate value-list comparisons into PyTables isin-style filters; only equality (==) and inequality (!=) are eligible. A non-equality comparison (>, <, >=, <=, in, not in) against a non-table source (e.g. a fixed-format store or an axis that is not indexed) cannot be expressed as a filter, so the engine rejects it with TypeError.

Solutions

  1. Write the store in table format with the relevant data_columns: store.put('df', df, format='table', data_columns=['A']).
  2. For fixed-format stores, read the whole frame and filter in pandas.
  3. Restrict where clauses on non-indexed sources to == / != (still require data_columns).
  4. Migrate new code to Parquet for richer predicate pushdown.

Example fix

// before
store.put('df', df)  # format='fixed' by default
store.select('df', where='A > 5')

// after
store.put('df', df, format='table', data_columns=['A'])
store.select('df', where='A > 5')
Defensive patterns

Strategy: validation

Validate before calling

def supports_filter(store, key: str) -> bool:
    storer = store.get_storer(key)
    return storer.is_table  # format='table' is required for filterable conditions

assert supports_filter(store, 'df'), 'store must be table format to support filterable where clauses'

Type guard

def is_table_store(store, key: str) -> bool:
    return bool(store.get_storer(key).is_table)

Try / catch

try:
    store.select('df', where='A > 5')
except TypeError as e:
    if 'filterable condition' in str(e):
        df = store.get('df')
        df[df['A'] > 5]
    else:
        raise

Prevention

When it happens

Trigger: store.select('df', where='A > 5') against a fixed-format store (format='fixed'), or where 'A' is not an in-table queryable. Using 'in'/'not in' against a non-indexed axis. Combining a non-equality op with a term whose is_in_table flag is False.

Common situations: Writing with the default format='fixed' (not queryable) and attempting a where clause. Expecting inequality filters on a non-table store. Querying an index level that is not materialized.

Related errors


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

Appendix: source

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

                self.filter[2],
            )
        return self

    def format(self):
        """return the actual filter format"""
        return [self.filter]

    # error: Signature of "evaluate" incompatible with supertype "BinOp"
    def evaluate(self) -> Self | None:  # type: ignore[override]
        if not self.is_valid:
            raise ValueError(f"query term is not valid [{self}]")

        rhs = self.conform(self.rhs)
        values = list(rhs)

        if self.op not in ["==", "!="]:
            if not self.is_in_table:
                raise TypeError(
                    f"passing a filterable condition to a non-table indexer [{self}]"
                )
            return None

        if self.is_in_table and len(values) <= self._max_selectors:
            return None
        filter_op = self.generate_filter_op()
        self.filter = (self.lhs.value, filter_op, Index(values))
        return self

    def generate_filter_op(self, invert: bool = False):
        if (self.op == "!=" and not invert) or (self.op == "==" and invert):
            return lambda axis, vals: ~axis.isin(vals)
        else:
            return lambda axis, vals: axis.isin(vals)


class JointFilterBinOp(FilterBinOp):

View on GitHub (pinned to 3b7651241d)