pandas-dev/pandas · error · TypeError

Cannot add {type(self).__name__} and {type(NaT).__name__}

Error message

Cannot add {type(self).__name__} and {type(NaT).__name__}

What it means

Raised by _add_nat when self.dtype is PeriodDtype. Adding pd.NaT to a PeriodArray is semantically unclear (Period + timedelta shifts by freq multiples, and NaT has no freq), so pandas refuses. For datetime/timedelta dtypes NaT is treated as a timedelta-like and returns all-NaT.

Source

Thrown at pandas/core/arrays/datetimelike.py:1205

            "DatetimeArray | TimedeltaArray", self
        )._ensure_matching_resos(other)
        return self._add_timedeltalike(other)

    @final
    def _add_timedeltalike(self, other: Timedelta | TimedeltaArray) -> Self:
        other_i8, o_mask = self._get_i8_values_and_mask(other)
        new_values = add_overflowsafe(self.asi8, np.asarray(other_i8, dtype="i8"))
        res_values = new_values.view(self._ndarray.dtype)

        return type(self)._simple_new(res_values, dtype=self.dtype)

    @final
    def _add_nat(self) -> Self:
        """
        Add pd.NaT to self
        """
        if isinstance(self.dtype, PeriodDtype):
            raise TypeError(
                f"Cannot add {type(self).__name__} and {type(NaT).__name__}"
            )

        # GH#19124 pd.NaT is treated like a timedelta for both timedelta
        # and datetime dtypes
        result = np.empty(self.shape, dtype=np.int64)
        result.fill(iNaT)
        result = result.view(self._ndarray.dtype)  # preserve reso
        return type(self)._simple_new(result, dtype=self.dtype)

    @final
    def _sub_nat(self) -> np.ndarray:
        """
        Subtract pd.NaT from self
        """
        # GH#19124 Timedelta - datetime is not in general well-defined.
        # We make an exception for pd.NaT, which in this case quacks
        # like a timedelta.

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. To null out a PeriodIndex elementwise, assign pd.NaT directly via .iloc or use idx.where(cond, other=pd.NaT).
  2. Convert to datetime if you need NaT arithmetic semantics: idx.to_timestamp() + pd.NaT.
  3. Add an integer multiple of the freq instead: period_idx + n shifts by n periods.
  4. Guard on isinstance(idx.dtype, pd.PeriodDtype) before generic NaT addition.

Example fix

// before
out = period_idx + pd.NaT  # TypeError
// after
out = period_idx.where(pd.Series([True, False, True]), other=pd.NaT)
Defensive patterns

Strategy: type-guard

Validate before calling

from pandas.api.types import is_period_dtype
if is_period_dtype(idx.dtype):
    out = idx.where(pd.Series([True]*len(idx)), other=pd.NaT)
else:
    out = idx + pd.NaT

Type guard

def rejects_nat_addition(idx) -> bool:
    from pandas.api.types import is_period_dtype
    return is_period_dtype(idx.dtype)

Try / catch

try:
    out = idx + pd.NaT
except TypeError as e:
    if 'Cannot add' in str(e) and 'NaT' in str(e):
        out = idx.where(pd.Series([True]*len(idx)), other=pd.NaT)
    else:
        raise

Prevention

When it happens

Trigger: PeriodIndex + pd.NaT, dispatched via __add__ line 1313 into _add_nat at line 1200; the PeriodDtype check at line 1204 fires.

Common situations: Generic 'fill with NaT' code paths that operate uniformly over Datetime/Timedelta/Period indexes; broadcasting NaT through mixed-dtype dictionaries.

Related errors


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