pandas-dev/pandas · error · ValueError

Unexpected value for 'dtype': '{dtype}'. Must be 'datetime64

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 dtype is a numpy dtype but not a supported datetime resolution (s/ms/us/ns), or is not an np.dtype/DatetimeTZDtype at all. Pandas lists exactly what it accepts and rejects everything else. ValueError.

Source

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

    -----
    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 71959b8cb9)

Solutions

  1. Use one of the supported resolutions: 'datetime64[s]', 'datetime64[ms]', 'datetime64[us]', 'datetime64[ns]'.
  2. For tz-aware data use a DatetimeTZDtype like 'datetime64[ns, Europe/London]'.
  3. If you need year/month/day granularity, build a PeriodIndex instead of a datetime dtype.

Example fix

# before
s.astype('datetime64[D]')
# after
s.astype('datetime64[ns]')
Defensive patterns

Strategy: validation

Validate before calling

ALLOWED = {'datetime64[s]', 'datetime64[ms]', 'datetime64[us]', 'datetime64[ns]'}
def validate_dt_dtype(dtype):
    if isinstance(dtype, str) and dtype not in ALLOWED and not dtype.startswith('datetime64['):
        raise ValueError(f"unsupported datetime dtype: {dtype!r}; use one of {sorted(ALLOWED)}")
    return dtype

Prevention

When it happens

Trigger: Passing dtype='datetime64[Y]', dtype='datetime64[D]' (unsupported units), dtype='int64', or a completely unrelated dtype string to a datetime constructor/astype.

Common situations: Assuming numpy's 'Y'/'M'/'D' units work (they don't in pandas); passing a numeric dtype to a datetime path; typos in the dtype string.

Related errors


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