pandas-dev/pandas · error · ValueError

Invalid dtype for PeriodArray

Error message

Invalid dtype {dtype} for PeriodArray

What it means

Raised by PeriodArray.__init__ when a dtype argument is supplied, resolved via pandas_dtype, but is not a PeriodDtype. PeriodArray is meaningful only with a frequency; passing an incompatible dtype (e.g. int64, datetime64, a string like 'M' that isn't a period unit) is rejected. The resolved dtype is included in the message.

Solutions

  1. Pass a proper period dtype: dtype='period[M]' or dtype=PeriodDtype('M').
  2. Omit dtype and let pandas infer the freq from Period scalars in the input.
  3. Build via pd.period_range(start, end, freq='M') which handles dtype for you.

Example fix

# before
pd.PeriodArray(pd.Series([pd.Period('2023', freq='Y')]), dtype='int64')  # raises

# after
pd.PeriodArray(pd.Series([pd.Period('2023', freq='Y')]), dtype='period[Y')
Defensive patterns

Strategy: validation

Validate before calling

import pandas as pd

def make_period_array(values, freq=None):
    dtype = f'period[{freq}]' if freq else None
    if dtype is not None:
        pd.core.dtypes.common.pandas_dtype(dtype)  # raises early if invalid
    return pd.PeriodArray(values, dtype=dtype)

Type guard

from pandas.core.dtypes.dtypes import PeriodDtype

def is_period_dtype_like(dtype) -> bool:
    try:
        return isinstance(pd.core.dtypes.common.pandas_dtype(dtype), PeriodDtype)
    except TypeError:
        return False

Try / catch

try:
    pd.PeriodArray(values, dtype=dtype)
except ValueError as e:
    if 'Invalid dtype' in str(e):
        pd.PeriodArray(values, dtype=f'period[{dtype}]')
    else:
        raise

Prevention

When it happens

Trigger: PeriodArray([2023, 2024], dtype='int64'); PeriodArray(values, dtype='datetime64[ns]'); PeriodArray(values, dtype='M') where 'M' parses to a non-Period dtype. Direct constructor use with the wrong dtype kind.

Common situations: Confusing Period freq strings ('M' = month period) with numpy/dateutil units; passing a plain frequency string where a period dtype ('period[M]') is required; copy-pasting dtype from a DatetimeIndex.

Related errors


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

Appendix: source

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

        "days_in_month",
    ]
    # GH#46768 - deprecated but still need to be accessible via .dt accessor
    _deprecated_ops: list[str] = ["dayofweek", "dayofyear", "daysinmonth"]
    _datetimelike_ops: list[str] = (
        _field_ops + _object_ops + _bool_ops + _deprecated_ops
    )
    _datetimelike_methods: list[str] = ["strftime", "to_timestamp", "asfreq"]

    _dtype: PeriodDtype

    # --------------------------------------------------------------------
    # Constructors

    def __init__(self, values, dtype: Dtype | None = None, copy: bool = False) -> None:
        if dtype is not None:
            dtype = pandas_dtype(dtype)
            if not isinstance(dtype, PeriodDtype):
                raise ValueError(f"Invalid dtype {dtype} for PeriodArray")

        if isinstance(values, ABCSeries):
            values = values._values
            if not isinstance(values, type(self)):
                raise TypeError("Incorrect dtype")

        elif isinstance(values, ABCPeriodIndex):
            values = values._values

        if isinstance(values, type(self)):
            if dtype is not None and dtype != values.dtype:
                raise raise_on_incompatible(values, dtype.freq)
            values, dtype = values._ndarray, values.dtype

        if not copy:
            values = np.asarray(values, dtype="int64")
        else:
            values = np.array(values, dtype="int64", copy=copy)

View on GitHub (pinned to 3b7651241d)