{"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":494,"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":476,"sourceCodeEnd":512,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/timedeltas.py#L476-L512","documentation":"Raised by TimedeltaArray._mul_float_overflowsafe when multiplying a timedelta64 array by a float whose products would exceed the int64 nanosecond range (~±292 years). Because numpy's int64-backed timedelta silently saturates at int64.max, pandas pre-checks the float64 product against 2**63 (not i8max, since i8max rounds up to 2**63 in float64) and raises OutOfBoundsTimedelta instead. NaT positions and NaN products are masked out before the bound check.","triggerScenarios":"Multiplying a large-magnitude timedelta by a large float: `pd.to_timedelta(10**17, unit='ns') * 1e6`, or scaling a long-duration Series by a float that pushes any element past ±2**63 nanoseconds.","commonSituations":"Unit-conversion arithmetic that accidentally uses ns-resolution magnitudes; aggregating or rescaling long durations (days/weeks) by large float weights.","solutions":["Reduce the multiplier so all products stay within ±2**63 nanoseconds (~292.3 years from zero).","Convert the timedelta to a coarser representation (e.g. compute in seconds via `.dt.total_seconds()`) before scaling, then cast back if needed.","Cap or clip extreme source values with `.clip()` before multiplication."],"exampleFix":"# before\npd.to_timedelta(10**17, unit='ns') * 1e6  # OutOfBoundsTimedelta\n\n# after\n(pd.to_timedelta(10**17, unit='ns') / 1e6).total_seconds()","handlingStrategy":"validation","validationCode":"import numpy as np\n\nNS_INT64_MAX = 2**63\n\ndef td_float_mul_is_safe(td_ns_values, factor):\n    arr = np.asarray(td_ns_values, dtype='i8')\n    arr = np.where(arr == np.int64(np.iinfo(np.int64).min), 0, arr)\n    return np.max(np.abs(arr.astype('f8') * factor), initial=0.0) < NS_INT64_MAX","typeGuard":"null","tryCatchPattern":"from pandas.errors import OutOfBoundsTimedelta\ntry:\n    result = td * factor\nexcept OutOfBoundsTimedelta:\n    # operate in coarser units to avoid the ns int64 ceiling\n    result = (td.dt.total_seconds() * factor)","preventionTips":["Prefer total_seconds()-based scaling for large magnitudes.","Bound-check float factors against the ±2**63 ns product before multiplying."],"tags":["timedelta","overflow","multiplication","outofbounds"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}