pandas-dev/pandas · error · TypeError

Expected array of boolean type, got {array.type} instead

Error message

Expected array of boolean type, got {array.type} instead

What it means

BooleanDtype.__from_arrow__ (boolean.py:141) requires the incoming pyarrow array to be of type bool (or null); any other arrow type (int, float, string, etc.) raises TypeError naming the actual type. This guards zero-copy construction of a BooleanArray from arrow buffers, which only makes sense for boolean arrow data.

Source

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

    @property
    def _is_boolean(self) -> bool:
        return True

    @property
    def _is_numeric(self) -> bool:
        return True

    def __from_arrow__(
        self, array: pyarrow.Array | pyarrow.ChunkedArray
    ) -> BooleanArray:
        """
        Construct BooleanArray from pyarrow Array/ChunkedArray.
        """
        import pyarrow

        if array.type != pyarrow.bool_() and not pyarrow.types.is_null(array.type):
            raise TypeError(f"Expected array of boolean type, got {array.type} instead")

        if isinstance(array, pyarrow.Array):
            chunks = [array]
            length = len(array)
        else:
            # pyarrow.ChunkedArray
            chunks = array.chunks
            length = array.length()

        if pyarrow.types.is_null(array.type):
            mask = np.ones(length, dtype=bool)
            # No need to init data, since all null
            data = np.empty(length, dtype=bool)
            return BooleanArray(data, mask)

        results = []
        for arr in chunks:
            buflist = arr.buffers()

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Cast the pyarrow array to bool before conversion: pa_array.cast(pa.bool_()).
  2. Let pandas infer the dtype and convert afterwards via pd.array(values, dtype='boolean').
  3. Fix the upstream schema so flag columns are produced as arrow bool.
  4. Drop the offending column or handle it with a separate path.

Example fix

# before
import pyarrow as pa
pa.array([1, 0, 1]).to_pandas(dtype="boolean")  # raises

# after
pa.array([1, 0, 1]).cast(pa.bool_()).to_pandas(dtype="boolean")
Defensive patterns

Strategy: validation

Validate before calling

def to_boolean_from_arrow(pa_arr):
    import pyarrow as pa
    if pa_arr.type != pa.bool_() and not pa.types.is_null(pa_arr.type):
        pa_arr = pa_arr.cast(pa.bool_())
    return pa_arr.to_pandas(dtype="boolean")

Type guard

def is_arrow_bool(pa_arr) -> bool:
    import pyarrow as pa
    return pa_arr.type == pa.bool_() or pa.types.is_null(pa_arr.type)

Try / catch

try:
    series = pa_array.to_pandas(dtype="boolean")
except TypeError as e:
    if "Expected array of boolean type" in str(e):
        import pyarrow as pa
        series = pa_array.cast(pa.bool_()).to_pandas(dtype="boolean")
    else:
        raise

Prevention

When it happens

Trigger: Converting a non-boolean pyarrow array to pandas with the 'boolean' dtype, e.g. table.schema.types mismatch, pa.array([1,0,1]).cast(...) then to_pandas(dtype='boolean'), or arrow exchange protocols that route a wrong-typed chunk into __from_arrow__.

Common situations: Reading parquet/arrow tables whose columns are int8/uint8 flags meant to be boolean; explicit dtype='boolean' on to_pandas; pyarrow schema mismatches after ETL.

Related errors


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