pandas-dev/pandas · error · TypeError

Cannot multiply StringArray by bools. Explicitly cast to…

Error message

Cannot multiply StringArray by bools. Explicitly cast to integers instead.

What it means

StringArray refuses multiplication by bool or bool-dtype arrays (GH#62595) because multiplying strings by booleans is ambiguous (repeat vs. mask). pandas requires an explicit integer cast so the intent (string repetition count) is unambiguous.

Solutions

  1. Cast the bool operand to int explicitly: s * other.astype(int).
  2. If repeating by 0/1 pattern was the goal, use s.where(other, '') or s.repeat(other.astype(int)).
  3. Replace bool with an integer count array conveying repetition counts.

Example fix

// before
s = pd.Series(['ab','cd'], dtype='string')
s * np.array([True, False])  # TypeError
// after
s * np.array([True, False]).astype(int)  # 'ab', ''
Defensive patterns

Strategy: validation

Validate before calling

def safe_mul(s, other):
    if pd.api.types.is_bool_dtype(pd.Series(other).dtype):
        other = pd.Series(other).astype(int)
    return s * other

Type guard

def is_non_bool_multiplier(other) -> bool:
    import numpy as np
    arr = np.asarray(other)
    return arr.dtype.kind != 'b'

Try / catch

try:
    s * other
except TypeError as e:
    if 'Cannot multiply StringArray by bools' in str(e):
        s * np.asarray(other).astype(int)
    else:
        raise

Prevention

When it happens

Trigger: s * True, s * [True, False], s * bool_series, or s * np.array([1,0], dtype=bool) where s is string-dtyped; op.__name__ in mul/rmul and lib.is_bool(other) or other has np dtype 'b'.

Common situations: Using a boolean mask as a multiplier instead of as an indexer; piping a condition into a multiplication instead of np.where; refactoring an int column to bool and breaking string repetition.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/70ccad7aae54da03. Report an issue: GitHub.

Appendix: source

Thrown at pandas/core/arrays/string_.py:1264

                    stacklevel=find_stack_level(),
                )
            if len(other) != len(self):
                # prevent improper broadcasting when other is 2D
                raise ValueError(
                    f"Lengths of operands do not match: {len(self)} != {len(other)}"
                )

            # for array-likes, first filter out NAs before converting to numpy
            if not is_array_like_deprecate_non_pandas(other):
                other = np.asarray(other)
            other = other[valid]

        other_dtype = getattr(other, "dtype", None)
        if op.__name__.strip("_") in ["mul", "rmul"] and (
            lib.is_bool(other) or lib.is_np_dtype(other_dtype, "b")
        ):
            # GH#62595
            raise TypeError(
                "Cannot multiply StringArray by bools. "
                "Explicitly cast to integers instead."
            )

        if op.__name__ in ops.ARITHMETIC_BINOPS:
            result = np.empty_like(self._ndarray, dtype="object")
            result[mask] = self.dtype.na_value
            result[valid] = op(self._ndarray[valid], other)
            if not lib.is_string_array(result, skipna=True):
                return result
            return self._from_backing_data(result)
        else:
            # logical
            result = np.zeros(len(self._ndarray), dtype="bool")
            result[valid] = op(self._ndarray[valid], other)
            res_arr = BooleanArray(result, mask)
            if self.dtype.na_value is np.nan:
                if op == operator.ne:

View on GitHub (pinned to 3b7651241d)