pandas-dev/pandas · error · ValueError

dtype must be PeriodDtype

Error message

dtype must be PeriodDtype

What it means

Raised by validate_dtype_freq when an explicit `dtype` is provided but is not a PeriodDtype. The helper validates that the dtype accompanying a period construction is genuinely period-typed before letting it through; anything else is rejected.

Source

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

    Parameters
    ----------
    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

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Pass a PeriodDtype: pd.PeriodDtype(freq) or 'period[freq]'.
  2. Omit dtype and let freq drive the inference.
  3. Validate dtype isinstance PeriodDtype at the caller boundary.

Example fix

# before
validate_dtype_freq('int64', None)
# after
validate_dtype_freq(pd.PeriodDtype('D'), None)
Defensive patterns

Strategy: type-guard

Validate before calling

from pandas.core.dtypes.dtypes import PeriodDtype
from pandas.core.arrays.period import validate_dtype_freq

def safe_validate(dtype, freq):
    if dtype is not None and not isinstance(dtype, PeriodDtype):
        dtype = None
    return validate_dtype_freq(dtype, freq)

Type guard

from pandas.core.dtypes.dtypes import PeriodDtype

def is_period_dtype(dtype) -> bool:
    return isinstance(dtype, PeriodDtype)

Try / catch

try:
    dt = validate_dtype_freq(dtype, freq)
except ValueError:
    dt = validate_dtype_freq(None, freq)

Prevention

When it happens

Trigger: Internal PeriodIndex/period_array construction paths that call validate_dtype_freq(dtype, freq) with a non-PeriodDtype first argument. Passing dtype='int64' or dtype=object where a period dtype is required.

Common situations: Wrapper libraries forwarding user dtypes into period constructors. Mixed dtype/freq APIs where the user supplies freq via dtype that isn't period-typed.

Related errors


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