pandas-dev/pandas · error · NotImplementedError
cannot evaluate scalar only bool ops
Error message
cannot evaluate scalar only bool ops
What it means
Raised by BinOp._disallow_scalar_only_bool_ops in pandas.core.computation.ops when a boolean operator (&, |, and, or) is applied between operands where at least one is a scalar AND not both sides are bool/np.bool_. pandas deliberately refuses to apply Python's bitwise-and/or to non-bool scalars (e.g. integers) because the result is ambiguous (bitwise vs logical). It is raised as NotImplementedError and is intentionally conservative.
Source
Thrown at pandas/core/computation/ops.py:487
rhs = self.rhs
lhs = self.lhs
# GH#24883 unwrap dtype if necessary to ensure we have a type object
rhs_rt = rhs.return_type
rhs_rt = getattr(rhs_rt, "type", rhs_rt)
lhs_rt = lhs.return_type
lhs_rt = getattr(lhs_rt, "type", lhs_rt)
if (
(lhs.is_scalar or rhs.is_scalar)
and self.op in _bool_ops_dict
and (
not (
issubclass(rhs_rt, (bool, np.bool_))
and issubclass(lhs_rt, (bool, np.bool_))
)
)
):
raise NotImplementedError("cannot evaluate scalar only bool ops")
UNARY_OPS_SYMS = ("+", "-", "~", "not")
_unary_ops_funcs = (operator.pos, operator.neg, operator.invert, operator.invert)
_unary_ops_dict = dict(zip(UNARY_OPS_SYMS, _unary_ops_funcs, strict=True))
class UnaryOp(Op):
"""
Hold a unary operator and its operands.
Parameters
----------
op : str
The token used to represent the operator.
operand : Term or Op
The Term or Op operand to the operator.
View on GitHub (pinned to 71959b8cb9)
Solutions
- Convert operands to bool explicitly before combining: pd.eval('(a > 0) & (b > 0)') instead of 'a & b'.
- If combining scalar truth values, use plain Python (x and y) outside of pd.eval, or pass them as bool(x) & bool(y).
- For integer bitwise AND, apply the operator directly on the Series outside eval (s1 & s2), or wrap with bool() if you truly want logical semantics.
Example fix
# before
import pandas as pd
pd.eval('1 & 2') # NotImplementedError: cannot evaluate scalar only bool ops
# after (logical)
pd.eval('bool(1) & bool(2)') # explicit bool cast
# after (bitwise on integers -> skip eval)
1 & 2 Defensive patterns
Strategy: validation
Validate before calling
def coerce_bool(value):
return bool(value) if not hasattr(value, '__iter__') else value.astype(bool)
# ensure both sides are bool before combining with & / | in eval
Type guard
import numpy as np
def is_bool_scalar(x) -> bool:
return isinstance(x, (bool, np.bool_))
Try / catch
try:
pd.eval('x & y', local_dict={'x': x, 'y': y})
except NotImplementedError as e:
if 'scalar only bool ops' in str(e):
# cast to bool and retry, or apply directly
result = bool(x) & bool(y)
else:
raise Prevention
- Wrap operands in explicit comparisons: '(a > 0) & (b > 0)' instead of 'a & b'.
- Cast scalars to bool before combining: bool(x) & bool(y).
- For bitwise integer ops, apply operators directly on Series outside eval.
When it happens
Trigger: pd.eval('@x & @y') with x,y being non-bool scalars (e.g. ints); pd.eval('1 & 2'); pd.eval('(a > 0) & 5') where one side collapses to a scalar. Also df.query('a & 3') where 3 is treated as a scalar.
Common situations: Treating pandas eval like Python and expecting 'and'/'&' to work on integer truthiness; mixing boolean column masks with scalar thresholds; migrating code from plain Python `and`/`or` to vectorized eval without converting operands to bool first.
Related errors
- {cls.__name__}(...) must be called with a collection of some
- Cannot construct {type(self).__name__} from scalar data. Pas
- The '@' prefix is only supported by the pandas parser
- The '@' prefix is not allowed in top-level eval calls. pleas
- expr must be a string to be evaluated, {type(expr)} given
AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07).
Data as JSON: /api/errors/534c3a057f3722f3.
Report an issue: GitHub.