pandas-dev/pandas · error · ValueError

Wrong dtype

Error message

Wrong dtype: {data.dtype}

What it means

Raised inside dt64arr_to_periodarr when the input array's dtype is not numpy datetime64 (kind != 'M'). The conversion path expects raw datetime64 values to translate into period ordinals; any other dtype (int, float, object, period, etc.) is refused here.

Solutions

  1. Coerce first: pd.to_datetime(series).to_period(freq).
  2. If you have ordinals already, construct PeriodIndex directly with the freq rather than going through this branch.
  3. For numeric epoch data, convert via pd.to_datetime(series, unit='s') first.

Example fix

# before
df['col'].to_period('M')  # col is object/str
# after
pd.to_datetime(df['col']).to_period('M')
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np

def is_datetime_array(arr) -> bool:
    return isinstance(arr.dtype, np.dtype) and arr.dtype.kind == 'M'

Type guard

import numpy as np

def to_period_ready(series) -> bool:
    return hasattr(series, 'dtype') and isinstance(series.dtype, np.dtype) and series.dtype.kind == 'M'

Try / catch

try:
    periods = series.to_period(freq)
except ValueError as e:
    if 'Wrong dtype' in str(e):
        periods = pd.to_datetime(series).to_period(freq)
    else:
        raise

Prevention

When it happens

Trigger: Calling Series.to_period()/DatetimeIndex.to_period() on data that is not datetime64; passing int epoch values or strings to a PeriodArray constructor that goes through the datetime-conversion branch; converting a PeriodIndex back through to_period.

Common situations: Forgetting to pd.to_datetime() a column of strings before .to_period(); loading CSV dates as object dtype and calling .to_period('M'); passing epoch ints assuming automatic conversion.

Related errors


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

Appendix: source

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

    Parameters
    ----------
    data : Union[Series[datetime64[ns]], DatetimeIndex, ndarray[datetime64ns]]
    freq : Optional[Union[str, Tick]]
        Must match the `freq` on the `data` if `data` is a DatetimeIndex
        or Series.
    tz : Optional[tzinfo]

    Returns
    -------
    ordinals : ndarray[int64]
    freq : Tick
        The frequency extracted from the Series or DatetimeIndex if that's
        used.

    """
    if not isinstance(data.dtype, np.dtype) or data.dtype.kind != "M":
        raise ValueError(f"Wrong dtype: {data.dtype}")

    if freq is None:
        if isinstance(data, ABCIndex):
            data, freq = data._values, data.freq
        elif isinstance(data, ABCSeries):
            # freq is always None for DatetimeArray inside a Series, so we
            #  fall back to the inferred freq.
            inferred_freq = data._values._inferred_freq_str
            if inferred_freq is not None:
                warnings.warn(
                    "Constructing PeriodArray from a Series of datetime64 data "
                    "will stop inferring the frequency in a future version. "
                    "Pass `freq` explicitly instead.",
                    Pandas4Warning,
                    stacklevel=find_stack_level(),
                )
                freq = inferred_freq
            data = data._values

View on GitHub (pinned to 3b7651241d)