{"record":{"id":"1ab8e29e7f3fd08b","repo":"pandas-dev/pandas","slug":"overflow-in-timedelta-multiplication","errorCode":null,"errorMessage":"Overflow in timedelta multiplication","messagePattern":"Overflow in timedelta multiplication","errorType":"exception","errorClass":"OutOfBoundsTimedelta","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/timedeltas.py","lineNumber":477,"sourceCode":"\n    def _mul_float_overflowsafe(\n        self, other: float | np.floating | npt.NDArray[np.floating]\n    ) -> Self:\n        # GH#43178: detect float products that would silently saturate to\n        #  int64.max on the int64 cast below\n        i8 = self.asi8\n        self_mask = i8 == iNaT\n        if self_mask.any():\n            # zero out NaT positions so they don't trigger the bounds check\n            i8 = np.where(self_mask, 0, i8)\n        f_result = i8 * other\n        nan_mask = np.isnan(f_result)\n        non_nan = f_result[~nan_mask]\n        # Compare against 2**63, not i8max: i8max (2**63 - 1) rounds up to\n        #  2**63 in float64, so a product landing exactly on 2**63 would slip\n        #  past a ``> i8max`` check and saturate on the cast. Also catches +/-inf.\n        if non_nan.size and np.max(np.abs(non_nan), initial=0.0) >= 2.0**63:\n            raise OutOfBoundsTimedelta(\"Overflow in timedelta multiplication\")\n        # NaN-to-int cast is platform-dependent; substitute 0 then re-mask as NaT\n        if nan_mask.any():\n            f_result = np.where(nan_mask, 0.0, f_result)\n        i8_result = f_result.astype(\"i8\")\n        nat_out = self_mask | nan_mask\n        if nat_out.any():\n            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)","sourceCodeStart":459,"sourceCodeEnd":495,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/arrays/timedeltas.py#L459-L495","documentation":"Raised by TimedeltaArray._mul_float_overflowsafe when a float multiplication of the int64 nanosecond ticks would produce a magnitude >= 2**63, exceeding the int64 range. The check (GH#43178) compares max(abs(non_nan)) against 2.0**63 (not i8max) to catch values that would round up to 2**63 in float64 and silently saturate on the i8 cast. It is raised as OutOfBoundsTimedelta to match pandas' other td64 overflow paths.","triggerScenarios":"Multiplying a large-magnitude timedelta64 array by a large float, e.g. `td_arr * 1e9` where td_arr values are already days. The bound check at timedeltas.py:476 triggers when the float product exceeds 2**63.","commonSituations":"Unit conversion helpers that multiply instead of using astype; scaling durations by large factors; feeding raw nanosecond ints through float math.","solutions":["Reduce the magnitude before multiplying: convert the array to a coarser supported unit via astype first.","Use a smaller multiplier and adjust units (e.g. multiply seconds, not nanoseconds).","Operate in Python decimals/objects if true large-magnitude products are required, then re-wrap carefully."],"exampleFix":"# before\n(td_arr * 1e9)  # OutOfBoundsTimedelta if td_arr in ns\n# after\ntd_arr.astype('timedelta64[s]') * 1e9","handlingStrategy":"validation","validationCode":"I8_MAX_NS = 2**63\n\ndef safe_float_mul(td_arr, factor):\n    peak = td_arr.asi8.max() * abs(factor)\n    if peak >= I8_MAX_NS:\n        td_arr = td_arr.astype('timedelta64[s]')\n    return td_arr * factor","typeGuard":"import numpy as np\ndef float_mul_will_overflow(td_arr, factor) -> bool:\n    return np.max(np.abs(td_arr.asi8)) * abs(factor) >= 2**63","tryCatchPattern":"from pandas.errors import OutOfBoundsTimedelta\ntry:\n    return td_arr * factor\nexcept OutOfBoundsTimedelta as e:\n    if 'Overflow in timedelta multiplication' in str(e):\n        return td_arr.astype('timedelta64[s]') * factor\n    raise","preventionTips":["Convert to a coarser unit before multiplying by large floats.","Avoid float intermediates for unit conversion; use astype.","Bound-check magnitudes in scaling helpers."],"tags":["timedelta","overflow","arithmetic","outofbounds"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}