pandas-dev/pandas · error · TypeError

cannot add the type {type(other).__name__} to a {type(self).

Error message

cannot add the type {type(other).__name__} to a {type(self).__name__}

What it means

Raised by TimedeltaArray._add_offset when an attempt is made to add a DateOffset/Tick-like object that is not handled by the dedicated Tick/Day fast paths. Timedelta + offset is generally undefined (offsets apply to datetimes, not durations), so adding an arbitrary offset to a TimedeltaArray raises TypeError naming both types. The assert at line 455 excludes Tick/Day which have their own handlers.

Source

Thrown at pandas/core/arrays/timedeltas.py:456

        return get_format_timedelta64(self, box=True)

    def _format_native_types(
        self, *, na_rep: str | float = "NaT", date_format=None, **kwargs
    ) -> npt.NDArray[np.object_]:
        from pandas.io.formats.format import get_format_timedelta64

        # Relies on TimeDelta._repr_base
        formatter = get_format_timedelta64(self, na_rep)
        # equiv: np.array([formatter(x) for x in self._ndarray])
        #  but independent of dimension
        return np.frompyfunc(formatter, 1, 1)(self._ndarray)

    # ----------------------------------------------------------------
    # Arithmetic Methods

    def _add_offset(self, other):
        assert not isinstance(other, (Tick, Day))
        raise TypeError(
            f"cannot add the type {type(other).__name__} to a {type(self).__name__}"
        )

    def _mul_float_overflowsafe(
        self, other: float | np.floating | npt.NDArray[np.floating]
    ) -> Self:
        # GH#43178: detect float products that would silently saturate to
        #  int64.max on the int64 cast below
        i8 = self.asi8
        self_mask = i8 == iNaT
        if self_mask.any():
            # zero out NaT positions so they don't trigger the bounds check
            i8 = np.where(self_mask, 0, i8)
        f_result = i8 * other
        nan_mask = np.isnan(f_result)
        non_nan = f_result[~nan_mask]
        # Compare against 2**63, not i8max: i8max (2**63 - 1) rounds up to
        #  2**63 in float64, so a product landing exactly on 2**63 would slip

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. If you want to shift datetimes, convert: apply the offset to a datetime Series instead of a timedelta one.
  2. If you need to add a Tick (e.g. pd.offsets.Hour(2)), convert it to a Timedelta first: `td_arr + pd.Timedelta(offset)`.
  3. Re-express the operation: durations add to durations via Timedelta, offsets add to timestamps.

Example fix

# before
arr + pd.offsets.MonthEnd(1)  # TypeError
# after
# apply offsets to datetimes, or:
arr + pd.Timedelta(days=1)
Defensive patterns

Strategy: type-guard

Validate before calling

import pandas as pd
from pandas._libs.tslibs import Timedelta
from pandas.tseries.offsets import Tick, Day

def add_offset_or_td(td_arr, other):
    if isinstance(other, (Tick, Day)):
        return td_arr + pd.Timedelta(other)
    if isinstance(other, pd.Timestamp):
        raise TypeError('add offsets to datetimes, not timedeltas')
    return td_arr + other

Type guard

import pandas as pd
from pandas.tseries.offsets import Tick, Day
def is_tick_or_timedelta(other) -> bool:
    return isinstance(other, (Tick, Day, pd.Timedelta))

Try / catch

try:
    return td_arr + other
except TypeError as e:
    if 'cannot add the type' in str(e):
        return td_arr + pd.Timedelta(other)
    raise

Prevention

When it happens

Trigger: Executing `td_arr + pd.offsets.MonthEnd()` or any `timedelta64 + DateOffset` expression. The dispatcher routes offset addition to _add_offset, which rejects non-Tick offsets.

Common situations: Treating a duration column like a datetime column and shifting by calendar offsets; merging logic that mixes timedelta and offset arithmetic.

Related errors


AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07). Data as JSON: /api/errors/730615daf513dd8a. Report an issue: GitHub.