pandas-dev/pandas · error · TypeError

Cannot add and

Error message

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

What it means

Raised by _add_nat when isinstance(self.dtype, PeriodDtype). Adding NaT to a PeriodArray is undefined (Period has no 'shift by missing duration' semantics), whereas for DatetimeArray/TimedeltaArray NaT is treated as a timedelta producing all-NaT. PeriodArray is therefore explicitly rejected.

Solutions

  1. Do not add NaT to a PeriodArray; if you need all-NaT output, construct it directly: PeriodArray(np.full(len, iNaT, dtype='i8'), dtype=self.dtype).
  2. Branch on dtype: handle Period separately (e.g. mask with isna() and assign pd.NaT rather than adding).
  3. If the NaT came from upstream computation, guard it: skip the addition when other is NaT.

Example fix

// before
res = parr + pd.NaT  # TypeError

// after
res = parr.copy()
res[:] = pd.NaT  # produce all-NaT PeriodArray without arithmetic
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np, pandas as pd

def add_nat_safe(arr):
    if isinstance(arr.dtype, pd.PeriodDtype):
        out = arr.copy()
        out[:] = pd.NaT
        return out
    return arr + pd.NaT

Type guard

import pandas as pd

def is_period_array(a) -> bool:
    return isinstance(getattr(a, 'dtype', None), pd.PeriodDtype)

Try / catch

try:
    res = arr + pd.NaT
except TypeError as e:
    if 'Cannot add' in str(e) and 'NaT' in str(e):
        out = arr.copy()
        out[:] = pd.NaT
        res = out
    else:
        raise

Prevention

When it happens

Trigger: PeriodArray + pd.NaT; PeriodIndex arithmetic where the right operand evaluates to NaT (e.g. result of a computation that yields NaT); fillna-style arithmetic that introduces NaT into a Period operation.

Common situations: Code generic over datetimelike dtypes that special-cases NaT for datetime/timedelta but is run against a PeriodIndex; NA-propagation logic that adds NaT to shift values.

Related errors


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

Appendix: 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 3b7651241d)