pandas-dev/pandas · error · ValueError

Unexpected value for 'dtype

Error message

Unexpected value for 'dtype': '{dtype}'. Must be 'datetime64[s]', 'datetime64[ms]', 'datetime64[us]', 'datetime64[ns]' or DatetimeTZDtype'.

What it means

Raised by _validate_dt64_dtype when the supplied dtype is a numpy dtype that is not an 'M' kind or is not a supported datetime resolution, OR is not a numpy.dtype / DatetimeTZDtype instance at all. The message enumerates the supported values. This is the catch-all dtype validation for datetime construction.

Solutions

  1. Verify the dtype string matches one of the supported forms exactly: 'datetime64[s]', 'datetime64[ms]', 'datetime64[us]', 'datetime64[ns]', or a DatetimeTZDtype like 'datetime64[ns, UTC]'.
  2. If the data is not yet datetime, first convert with `pd.to_datetime(values)` and only then specify a datetime dtype.
  3. If you wanted a non-datetime dtype, use `pd.Series` not `pd.DatetimeIndex`.
  4. For tz-aware targets, prefer constructing a DatetimeTZDtype object explicitly: `pd.DatetimeTZDtype(tz='UTC', unit='ns')`.

Example fix

// before
dti = pd.DatetimeIndex(values, dtype='datetime64[n]')

// after
dti = pd.DatetimeIndex(values, dtype='datetime64[ns]')
Defensive patterns

Strategy: validation

Validate before calling

import pandas as pd

VALID = {'datetime64[s]', 'datetime64[ms]', 'datetime64[us]', 'datetime64[ns]'}
def is_supported_dt_dtype_string(s: str) -> bool:
    if s in VALID:
        return True
    try:
        return isinstance(pd.DatetimeTZDtype.construct_from_string(s), pd.DatetimeTZDtype)
    except TypeError:
        return False

Type guard

import pandas as pd
def is_datetime_dtype_spec(s) -> bool:
    try:
        dt = pd.api.types.pandas_dtype(s)
    except TypeError:
        return False
    return isinstance(dt, (np.dtype, pd.DatetimeTZDtype)) and (dt.kind == 'M' or isinstance(dt, pd.DatetimeTZDtype))

Try / catch

try:
    dti = pd.DatetimeIndex(values, dtype=dtype_str)
except ValueError as e:
    if "Unexpected value for 'dtype'" in str(e):
        dti = pd.DatetimeIndex(values)  # let pandas pick
    else:
        raise

Prevention

When it happens

Trigger: Passing `dtype='int64'`, `dtype='float64'`, `dtype='object'`, `dtype='datetime64[fs]'` (unsupported unit), `dtype='category'`, or any non-datetime dtype to a DatetimeIndex/DatetimeArray constructor routed through _validate_dt64_dtype.

Common situations: Typo in a unit string (e.g. 'datetime64[n]'). Confusing a Series constructor (which accepts any dtype) with a DatetimeIndex constructor (which only accepts datetime dtypes). Programmatic code that passes whatever dtype a column currently has into a datetime-conversion call.

Related errors


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

Appendix: source

Thrown at pandas/core/arrays/datetimes.py:2988

    -----
    Unlike _validate_tz_from_dtype, this does _not_ allow non-existent
    tz errors to go through
    """
    if dtype is not None:
        dtype = pandas_dtype(dtype)
        if dtype == np.dtype("M8"):
            # no precision, disallowed GH#24806
            msg = (
                "Passing in 'datetime64' dtype with no precision is not allowed. "
                "Please pass in 'datetime64[ns]' instead."
            )
            raise ValueError(msg)

        if (
            isinstance(dtype, np.dtype)
            and (dtype.kind != "M" or not is_supported_dtype(dtype))
        ) or not isinstance(dtype, (np.dtype, DatetimeTZDtype)):
            raise ValueError(
                f"Unexpected value for 'dtype': '{dtype}'. "
                "Must be 'datetime64[s]', 'datetime64[ms]', 'datetime64[us]', "
                "'datetime64[ns]' or DatetimeTZDtype'."
            )

        if getattr(dtype, "tz", None):
            # https://github.com/pandas-dev/pandas/issues/18595
            # Ensure that we have a standard timezone for pytz objects.
            # Without this, things like adding an array of timedeltas and
            # a  tz-aware Timestamp (with a tz specific to its datetime) will
            # be incorrect(ish?) for the array as a whole
            dtype = cast("DatetimeTZDtype", dtype)
            dtype = DatetimeTZDtype(
                unit=dtype.unit, tz=timezones.tz_standardize(dtype.tz)
            )

    return dtype

View on GitHub (pinned to 3b7651241d)