pandas-dev/pandas · error · TypeError

'other' should be pandas.NA or a bool. Got {type(other).__na

Error message

'other' should be pandas.NA or a bool. Got {type(other).__name__} instead.

What it means

BooleanArray._logical_method (boolean.py:421) enforces Kleene-logic semantics: when the other operand is a scalar that is neither pandas.NA nor a Python bool, it raises TypeError listing the actual type. Logical ops on BooleanArray require bool/NA operands to keep three-valued logic well-defined.

Source

Thrown at pandas/core/arrays/boolean.py:421

            ) and not ops.has_castable_attr(other):
                warnings.warn(
                    f"Operation with {type(other).__name__} is deprecated. "
                    "In a future version these will be treated as scalar-like. "
                    "To retain the old behavior, explicitly wrap in a Series "
                    "instead.",
                    Pandas4Warning,
                    stacklevel=find_stack_level(),
                )

            other = np.asarray(other, dtype="bool")
            if other.ndim > 1:
                return NotImplemented
            other, mask = coerce_to_array(other, copy=False)
        elif isinstance(other, np.bool_):
            other = other.item()

        if other_is_scalar and other is not libmissing.NA and not lib.is_bool(other):
            raise TypeError(
                "'other' should be pandas.NA or a bool. "
                f"Got {type(other).__name__} instead."
            )

        if not other_is_scalar and len(self) != len(other):
            raise ValueError("Lengths must match")

        if op.__name__ in {"or_", "ror_"}:
            result, mask = ops.kleene_or(self._data, other, self._mask, mask)
        elif op.__name__ in {"and_", "rand_"}:
            result, mask = ops.kleene_and(self._data, other, self._mask, mask)
        else:
            # i.e. xor, rxor
            result, mask = ops.kleene_xor(self._data, other, self._mask, mask)

        # i.e. BooleanArray
        return self._maybe_mask_result(result, mask)

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Convert the operand to bool first: ba & bool(flag).
  2. Use pandas.NA explicitly for missing logical operands.
  3. Wrap list-like operands in a Series/array of bool instead of a scalar.
  4. For integer-flag logic, convert the BooleanArray to Int64 and use arithmetic instead of bitwise ops.

Example fix

# before
ba = pd.array([True, False], dtype="boolean")
ba & 1  # raises

# after
ba & True
# or
ba & bool(1)
Defensive patterns

Strategy: type-guard

Validate before calling

def safe_logical(ba, other):
    import pandas as pd
    import numpy as np
    if pd.isna(other) or isinstance(other, (bool, np.bool_)):
        return ba & other
    return ba & bool(other)

Type guard

def is_bool_or_na(x) -> bool:
    import pandas as pd
    import numpy as np
    return x is pd.NA or isinstance(x, (bool, np.bool_))

Try / catch

try:
    result = ba & other
except TypeError as e:
    if "should be pandas.NA or a bool" in str(e):
        result = ba & bool(other)
    else:
        raise

Prevention

When it happens

Trigger: ba & 5, ba | 'x', ba ^ 1.5, or any bitwise logical op between a BooleanArray and a non-bool scalar (int, float, str).

Common situations: Mixing integer flags with boolean arrays via bitwise operators; assuming NumPy-style broadcasting of arbitrary scalars into bool ops; refactor that replaced a bool with an int variable.

Related errors


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