pandas-dev/pandas · error · OutOfBoundsTimedelta

overflow in timedelta operation

Error message

overflow in timedelta operation

What it means

OutOfBoundsTimedelta raised in datetimelike_accumulations when a cumsum on a timedelta array produces a total whose int64 nanosecond representation wraps (signed overflow) or equals NaT (int64.min). Pandas detects the wrap by checking step direction against the addend sign and refuses to return an incorrect result.

Solutions

  1. Reduce the magnitude: aggregate at a coarser unit by converting to a smaller dtype after summing per-chunk.
  2. Filter or resample the series so the running total stays within int64 nanosecond range.
  3. Compute cumsum on integer seconds/minutes (s.astype('int64')//unit) and convert back to timedelta at the end.
Defensive patterns

Strategy: validation

Validate before calling

NS_INT64_MAX = (2**63 - 1)

def timedelta_cumsum_safe(s):
    total_ns = s.dt.total_seconds().sum() * 1e9
    if abs(total_ns) > NS_INT64_MAX:
        raise OverflowError('cumsum would overflow int64 nanoseconds; resample or chunk first')
    return s.cumsum()

Try / catch

from pandas.errors import OutOfBoundsTimedelta
try:
    s.cumsum()
except OutOfBoundsTimedelta:
    # fall back to per-chunk cumsum on a coarser unit
    (s.dt.total_seconds().cumsum() * 1e9).astype('timedelta64[ns]')

Prevention

When it happens

Trigger: pd.Series(pd.to_timedelta([...])).cumsum() where the running sum exceeds the int64 nanosecond range (~292 years); cumsum on long-running timestamp differences.

Common situations: Aggregating many large timedelta values (e.g. days-scale durations over millions of rows); processing log/event durations whose cumulative total passes int64.max nanoseconds.

Related errors


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

Appendix: source

Thrown at pandas/core/array_algos/datetimelike_accumulations.py:50

    mask : np.ndarray[bool]
        Positions whose result will be NaT regardless, and so are exempt.
    """
    # Whether each running total is greater than the one before it, taking the
    #  total before the first entry to be zero.
    stepped_up = np.empty(result.shape, dtype=bool)
    np.greater(result[:1], 0, out=stepped_up[:1])
    np.greater(result[1:], result[:-1], out=stepped_up[1:])

    # Absent a signed wrap, the total goes up exactly when the addend is
    #  positive; a wrap flips the direction of the step.
    invalid = (values > 0) != stepped_up
    # A total of exactly int64.min does not wrap, but is indistinguishable
    #  from NaT once stored.
    invalid |= result == iNaT
    invalid &= ~mask

    if invalid.any():
        raise OutOfBoundsTimedelta("overflow in timedelta operation")


def _cum_func(
    func: Callable,
    values: np.ndarray,
    *,
    skipna: bool = True,
) -> np.ndarray:
    """
    Accumulations for 1D datetimelike arrays.

    Parameters
    ----------
    func : np.cumsum, np.maximum.accumulate, np.minimum.accumulate
    values : np.ndarray
        Numpy array with the values (can be of any dtype that support the
        operation). Values is changed is modified inplace.
    skipna : bool, default True

View on GitHub (pinned to 3b7651241d)