pandas-dev/pandas · error · IncompatibleFrequency

Cannot add/subtract timedelta-like from PeriodArray that is…

Error message

Cannot add/subtract timedelta-like from PeriodArray that is not an integer multiple of the PeriodArray's freq.

What it means

Raised by PeriodArray._time_shift when astype_overflowsafe cannot losslessly convert the timedelta operand into the period's timedelta unit (round_ok=False). The operation requires the delta to be an exact integer multiple of the period's tick; a sub-multiple (e.g. 30 seconds with a minute freq) cannot be represented and raises IncompatibleFrequency.

Solutions

  1. Round the delta to a whole multiple of the period: (delta // idx.freq) * idx.freq, then add.
  2. Switch to a finer period freq that the delta divides evenly (e.g. 's' instead of 'min').
  3. Quantize the timedelta to the period unit before adding: delta.round(idx.freq).

Example fix

# before
idx = pd.period_range('2023-01-01', periods=3, freq='min')
idx + pd.Timedelta('30s')  # raises

# after
idx + pd.Timedelta('60s')   # whole-minute delta
# or
idx.to_timestamp() + pd.Timedelta('30s')
Defensive patterns

Strategy: validation

Validate before calling

import pandas as pd

def add_timedelta_to_period(period_idx, delta):
    freq = period_idx.freq
    delta = pd.Timedelta(delta)
    n_periods = delta // pd.Timedelta(freq.nanos) if hasattr(freq, 'nanos') else None
    if n_periods is None or delta != n_periods * pd.Timedelta(freq.nanos):
        raise ValueError(f'{delta} is not an integer multiple of {freq}')
    return period_idx + int(n_periods) * freq

Type guard

import pandas as pd

def is_whole_period_multiple(delta, freq) -> bool:
    try:
        delta = pd.Timedelta(delta)
        return delta == (delta // pd.Timedelta(freq.nanos)) * pd.Timedelta(freq.nanos)
    except (ValueError, AttributeError, TypeError):
        return False

Try / catch

try:
    period_idx + delta
except Exception as e:  # IncompatibleFrequency subclasses ValueError
    if 'integer multiple' in str(e):
        delta = (pd.Timedelta(delta) // pd.Timedelta(period_idx.freq.nanos)) * period_idx.freq
        period_idx + delta
    else:
        raise

Prevention

When it happens

Trigger: minute_idx + pd.Timedelta('30s') — 30s is half a minute. daily_idx + np.timedelta64(12, 'h') — 12h is not a whole day. hourly_idx + pd.Timedelta('90s') where 90s doesn't divide the hour evenly into the array's unit.

Common situations: Sub-period deltas from sensor/IoT data; rounding errors in computed Timedeltas; mixing freq units (minutes + seconds) without alignment.

Related errors


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

Appendix: source

Thrown at pandas/core/arrays/period.py:1283

        """
        if not self.dtype._is_tick_like():
            # We cannot add timedelta-like to non-tick PeriodArray
            raise TypeError(
                f"Cannot add or subtract timedelta64[ns] dtype from {self.dtype}"
            )

        dtype = np.dtype(f"m8[{self.dtype._td64_unit}]")

        # Similar to _check_timedeltalike_freq_compat, but we raise with a
        #  more specific exception message if necessary.
        try:
            delta = astype_overflowsafe(
                np.asarray(other), dtype=dtype, copy=False, round_ok=False
            )
        except ValueError as err:
            # e.g. if we have minutes freq and try to add 30s
            # "Cannot losslessly convert units"
            raise IncompatibleFrequency(
                "Cannot add/subtract timedelta-like from PeriodArray that is "
                "not an integer multiple of the PeriodArray's freq."
            ) from err

        res_values = add_overflowsafe(self.asi8, np.asarray(delta.view("i8")))
        return type(self)(res_values, dtype=self.dtype)

    def _check_timedeltalike_freq_compat(self, other):
        """
        Arithmetic operations with timedelta-like scalars or array `other`
        are only valid if `other` is an integer multiple of `self.freq`.
        If the operation is valid, find that integer multiple.  Otherwise,
        raise because the operation is invalid.

        Parameters
        ----------
        other : timedelta, np.timedelta64, Tick,
                ndarray[timedelta64], TimedeltaArray, TimedeltaIndex

View on GitHub (pinned to 3b7651241d)