{"record":{"id":"e75367a212290305","repo":"pandas-dev/pandas","slug":"cannot-multiply-self-dtype-by-bool-explicitly","errorCode":null,"errorMessage":"Cannot multiply '{self.dtype}' by bool, explicitly cast to integers instead","messagePattern":"Cannot multiply '(.+?)' by bool, explicitly cast to integers instead","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/timedeltas.py","lineNumber":502,"sourceCode":"            i8_result[nat_out] = iNaT\n        result = i8_result.view(self._ndarray.dtype)\n        return type(self)._simple_new(result, dtype=result.dtype)\n\n    def _mul_int_overflowsafe(self, i8_other: npt.NDArray[np.int64]) -> Self:\n        # GH#43178: mul_overflowsafe raises the low-level OverflowError; surface\n        #  it as OutOfBoundsTimedelta to match pandas' other td64 overflow paths.\n        try:\n            i8_result = mul_overflowsafe(self.asi8, i8_other)\n        except OverflowError as err:\n            raise OutOfBoundsTimedelta(\"Overflow in int64 multiplication\") from err\n        result = i8_result.view(self._ndarray.dtype)\n        return type(self)._simple_new(result, dtype=result.dtype)\n\n    @unpack_zerodim_and_defer(\"__mul__\")\n    def __mul__(self, other) -> Self:\n        if is_scalar(other):\n            if lib.is_bool(other):\n                raise TypeError(\n                    f\"Cannot multiply '{self.dtype}' by bool, explicitly cast to \"\n                    \"integers instead\"\n                )\n            if lib.is_integer(other):\n                # GH#43178: detect int64 overflow rather than silently wrapping\n                #  in the i8 cast below (e.g. a multiplier outside int64 bounds).\n                # TODO(numpy>=2.5): numpy detects this natively (numpy GH-31378)\n                #  but raises OverflowError; once the numpy floor is >= 2.5, drop\n                #  mul_overflowsafe and re-wrap numpy's error as\n                #  OutOfBoundsTimedelta. The float path isn't covered and stays.\n                other = int(other)\n                if other > lib.i8max or other < -lib.i8max - 1:\n                    raise OutOfBoundsTimedelta(\"Overflow in int64 multiplication\")\n                i8_vals = self.asi8\n                if other != 0 and i8_vals.size:\n                    # The extreme elements bound all products, so checking them\n                    #  with exact Python-int arithmetic lets the common\n                    #  no-overflow case use a vectorized multiply. NaT","sourceCodeStart":484,"sourceCodeEnd":520,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/arrays/timedeltas.py#L484-L520","documentation":"Raised by TimedeltaArray.__mul__ when the scalar operand is a Python/numpy bool (GH#58054). Multiplying a duration by True/False is almost always a bug (True repeats once, False yields zero-length/NaT), so pandas requires an explicit integer cast to make intent clear. The same restriction applies to bool-dtype arrays (line 545). This aligns with numpy's deprecation of bool*number arithmetic.","triggerScenarios":"Executing `td_arr * True`, `td_arr * np.bool_(False)`, or `td_arr * bool_series`. The scalar check at timedeltas.py:501 uses lib.is_bool(other); the array check at line 543 uses other.dtype.kind=='b'.","commonSituations":"Using a boolean mask as a multiplier instead of as a selector; piping comparison results into arithmetic; legacy code relying on implicit bool-to-int coercion.","solutions":["Cast the bool to int: `td_arr * mask.astype('int64')` or `td_arr * int(mask)`.","If you meant filtering, use boolean indexing `td_arr[mask]` instead of multiplication.","Replace bool-as-multiplier logic with np.where if you need conditional scaling."],"exampleFix":"# before\ntd_arr * (td_arr > pd.Timedelta(0))  # TypeError\n# after\ntd_arr * (td_arr > pd.Timedelta(0)).astype('int64')","handlingStrategy":"type-guard","validationCode":"from pandas._libs import lib\n\ndef safe_td_mul(td_arr, other):\n    if lib.is_bool(other) or (hasattr(other, 'dtype') and other.dtype.kind == 'b'):\n        other = other.astype('int64') if hasattr(other, 'astype') else int(other)\n    return td_arr * other","typeGuard":"from pandas._libs import lib\ndef is_bool_operand(other) -> bool:\n    if lib.is_bool(other):\n        return True\n    dt = getattr(other, 'dtype', None)\n    return dt is not None and dt.kind == 'b'","tryCatchPattern":"try:\n    return td_arr * mask\nexcept TypeError as e:\n    if 'Cannot multiply' in str(e) and 'bool' in str(e):\n        return td_arr * mask.astype('int64')\n    raise","preventionTips":["Never multiply durations by bool masks; use indexing or np.where.","Cast bool operands to int explicitly.","Lint for `timedelta *` near boolean expressions."],"tags":["timedelta","boolean","arithmetic","typeerror"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}