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
- Write the store in table format with the relevant data_columns: store.put('df', df, format='table', data_columns=['A']).
- For fixed-format stores, read the whole frame and filter in pandas.
- Restrict where clauses on non-indexed sources to == / != (still require data_columns).
- 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
- Write queryable stores with format='table' and explicit data_columns.
- Reserve fixed-format stores for full reads only.
- Route inequality predicates through pandas for non-table stores.
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
- query term is not valid
- unable to collapse Joint Filters
- arithmetic operations are not supported inside an HDFStore…
- Cannot compare of type to column
- cannot subscript with
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)