pandas-dev/pandas · error · IncompatibleFrequency

specified freq and dtype are different

Error message

specified freq and dtype are different

What it means

Raised by validate_dtype_freq as pandas.errors.IncompatibleFrequency when both an explicit dtype (PeriodDtype) and a freq-derived dtype2 are supplied but they disagree. Pandas refuses to silently pick one frequency over the other because that would change period semantics.

Solutions

  1. Pick one source of truth: pass only freq or only dtype=pd.PeriodDtype(freq), not both.
  2. If conversion is intended, use PeriodIndex.asfreq(target_freq) on the existing index instead of re-constructing.
  3. Reconcile the two literals so freq matches the dtype's freq.

Example fix

# before
pd.period_range('2020', periods=3, freq='D', dtype=pd.PeriodDtype('M'))
# after
pd.period_range('2020', periods=3, freq='D')
# or convert explicitly
pd.period_range('2020', periods=3, freq='M').asfreq('D')
Defensive patterns

Strategy: validation

Validate before calling

from pandas import PeriodDtype

def reconcile(freq, dtype):
    if freq is not None and dtype is not None:
        derived = PeriodDtype(freq) if isinstance(freq, str) else PeriodDtype(freq.freqstr)
        if derived != dtype:
            raise ValueError(f'freq {freq!r} disagrees with dtype {dtype!r}')
    return dtype

Type guard

def freq_matches_dtype(freq, dtype) -> bool:
    if dtype is None or freq is None:
        return True
    return pd.PeriodDtype(freq) == dtype

Try / catch

from pandas.errors import IncompatibleFrequency
try:
    pi = pd.period_range(start, periods=n, freq=freq, dtype=dtype)
except IncompatibleFrequency:
    pi = pd.period_range(start, periods=n, freq=freq)  # drop dtype

Prevention

When it happens

Trigger: Calling period_range/PeriodIndex/PeriodArray with freq='D' and dtype=pd.PeriodDtype('M'); constructing PeriodIndex from existing Period objects of one frequency while passing freq= of another; converting between Period dtypes via construction instead of .asfreq().

Common situations: Refactoring code that changed the freq literal but left a stale dtype kwarg; building from a Series of Period('2020', 'A') values while passing freq='Q'; user input plumbing both freq and dtype independently.

Related errors


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

Appendix: source

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

    ----------
    dtype : dtype
    dtype2 : PeriodDtype or None
        Dtype derived from a `freq` passed to the caller.

    Returns
    -------
    PeriodDtype or None

    Raises
    ------
    ValueError : non-period dtype
    IncompatibleFrequency : mismatch between dtype and freq
    """
    if dtype is not None:
        if not isinstance(dtype, PeriodDtype):
            raise ValueError("dtype must be PeriodDtype")
        if dtype2 is not None and dtype != dtype2:
            raise IncompatibleFrequency("specified freq and dtype are different")

    elif dtype2 is not None:
        if not isinstance(dtype2, PeriodDtype):
            raise ValueError("dtype must be PeriodDtype")
        dtype = dtype2

    return dtype


def dt64arr_to_periodarr(
    data, freq, tz=None
) -> tuple[npt.NDArray[np.int64], BaseOffset]:
    """
    Convert a datetime-like array to values Period ordinals.

    Parameters
    ----------
    data : Union[Series[datetime64[ns]], DatetimeIndex, ndarray[datetime64ns]]

View on GitHub (pinned to 3b7651241d)