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

  1. Convert operands to bool explicitly before combining: pd.eval('(a > 0) & (b > 0)') instead of 'a & b'.
  2. If combining scalar truth values, use plain Python (x and y) outside of pd.eval, or pass them as bool(x) & bool(y).
  3. 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

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


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