{"record":{"id":"8fcc3d84bd356ebb","repo":"pandas-dev/pandas","slug":"cannot-add-subtract-timedelta-like-from-periodarra","errorCode":null,"errorMessage":"Cannot add/subtract timedelta-like from PeriodArray that is not an integer multiple of the PeriodArray's freq.","messagePattern":"Cannot add/subtract timedelta-like from PeriodArray that is not an integer multiple of the PeriodArray's freq\\.","errorType":"exception","errorClass":"IncompatibleFrequency","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/period.py","lineNumber":1273,"sourceCode":"        \"\"\"\n        if not self.dtype._is_tick_like():\n            # We cannot add timedelta-like to non-tick PeriodArray\n            raise TypeError(\n                f\"Cannot add or subtract timedelta64[ns] dtype from {self.dtype}\"\n            )\n\n        dtype = np.dtype(f\"m8[{self.dtype._td64_unit}]\")\n\n        # Similar to _check_timedeltalike_freq_compat, but we raise with a\n        #  more specific exception message if necessary.\n        try:\n            delta = astype_overflowsafe(\n                np.asarray(other), dtype=dtype, copy=False, round_ok=False\n            )\n        except ValueError as err:\n            # e.g. if we have minutes freq and try to add 30s\n            # \"Cannot losslessly convert units\"\n            raise IncompatibleFrequency(\n                \"Cannot add/subtract timedelta-like from PeriodArray that is \"\n                \"not an integer multiple of the PeriodArray's freq.\"\n            ) from err\n\n        res_values = add_overflowsafe(self.asi8, np.asarray(delta.view(\"i8\")))\n        return type(self)(res_values, dtype=self.dtype)\n\n    def _check_timedeltalike_freq_compat(self, other):\n        \"\"\"\n        Arithmetic operations with timedelta-like scalars or array `other`\n        are only valid if `other` is an integer multiple of `self.freq`.\n        If the operation is valid, find that integer multiple.  Otherwise,\n        raise because the operation is invalid.\n\n        Parameters\n        ----------\n        other : timedelta, np.timedelta64, Tick,\n                ndarray[timedelta64], TimedeltaArray, TimedeltaIndex","sourceCodeStart":1255,"sourceCodeEnd":1291,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/arrays/period.py#L1255-L1291","documentation":"Raised by PeriodArray._add_timedelta_arraylike when astype_overflowsafe cannot losslessly convert the timedelta to the period's tick unit with round_ok=False. Example: a minutes-freq period array plus 30 seconds — 30s is not a whole number of minutes — so there is no valid ordinal delta.","triggerScenarios":"period_range(freq='min') + pd.Timedelta(seconds=30); period freq='h' plus 90 minutes works (1.5h fails only if not a multiple); mismatched sub-tick timedeltas.","commonSituations":"Sensor data with second-level offsets on minute-period columns. Timezone/DST math producing non-integer offsets. User input mixing units (hours + seconds) naively.","solutions":["Round the timedelta to a whole multiple of the freq: Timedelta(seconds=60).","Choose a finer freq: pa.asfreq('s') + Timedelta(seconds=30).","Shift by integer periods: pa + n where n is the count of freq steps."],"exampleFix":"# before\npa = pd.period_range('2020-01-01 00:00','2020-01-01 02:00', freq='min')._data\npa + pd.Timedelta(seconds=30)\n# after\npa + pd.Timedelta(minutes=1)\n# or finer freq\npa.asfreq('s') + pd.Timedelta(seconds=30)","handlingStrategy":"validation","validationCode":"import pandas as pd\n\ndef timedelta_is_multiple_of(td: pd.Timedelta, freq: str) -> bool:\n    base = pd.Timedelta(1, unit={'min':'min','h':'h','s':'s','D':'D','us':'us','ns':'ns'}.get(freq, 's'))\n    return td % base == pd.Timedelta(0)","typeGuard":"import pandas as pd\n\ndef is_whole_multiple(td, pa) -> bool:\n    unit = pa.dtype._td64_unit\n    base = pd.Timedelta(1, unit=unit)\n    return td % base == pd.Timedelta(0)","tryCatchPattern":"from pandas.errors import IncompatibleFrequency\ntry:\n    out = pa + td\nexcept IncompatibleFrequency:\n    out = pa.asfreq('s') + td","preventionTips":["Snap timedeltas to whole multiples of the period freq.","Choose a freq at least as fine as the smallest offset you add.","Catch IncompatibleFrequency and degrade to a finer freq."],"tags":["period","arithmetic","timedelta","freq","pandas-arrays"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}