pandas-dev/pandas · error · ValueError

Cannot pass both a timezone-aware dtype and tz=None

Error message

Cannot pass both a timezone-aware dtype and tz=None

What it means

Raised by _validate_tz_from_dtype (with explicit_tz_none) when the user passes a timezone-aware dtype together with tz=None explicitly. Passing tz=None to force naive data conflicts with a tz-aware dtype, so it is rejected. ValueError.

Source

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

    ------
    ValueError : on tzinfo mismatch
    """
    if dtype is not None:
        if isinstance(dtype, str):
            try:
                dtype = DatetimeTZDtype.construct_from_string(dtype)
            except TypeError:
                # Things like `datetime64[ns]`, which is OK for the
                # constructors, but also nonsense, which should be validated
                # but not by us. We *do* allow non-existent tz errors to
                # go through
                pass
        dtz = getattr(dtype, "tz", None)
        if dtz is not None:
            if tz is not None and not timezones.tz_compare(tz, dtz):
                raise ValueError("cannot supply both a tz and a dtype with a tz")
            if explicit_tz_none:
                raise ValueError("Cannot pass both a timezone-aware dtype and tz=None")
            tz = dtz

        if tz is not None and lib.is_np_dtype(dtype, "M"):
            # We also need to check for the case where the user passed a
            #  tz-naive dtype (i.e. datetime64[ns])
            if tz is not None and not timezones.tz_compare(tz, dtz):
                raise ValueError(
                    "cannot supply both a tz and a "
                    "timezone-naive dtype (i.e. datetime64[ns])"
                )

    return tz


def _infer_tz_from_endpoints(
    start: Timestamp, end: Timestamp, tz: tzinfo | None
) -> tzinfo | None:
    """

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Drop tz=None and let the dtype's tz win.
  2. Or pass a tz-naive dtype ('datetime64[ns]') if you genuinely want naive output.
  3. Refactor wrappers to use a sentinel (e.g. lib.no_default) instead of tz=None when 'unspecified' is meant.

Example fix

# before
pd.DatetimeIndex(data, dtype='datetime64[ns, UTC]', tz=None)
# after
pd.DatetimeIndex(data, dtype='datetime64[ns, UTC]')
Defensive patterns

Strategy: validation

Validate before calling

def resolve_tz(dtype=None, tz=None):
    dt_tz = getattr(dtype, 'tz', None)
    if dt_tz is not None and tz is None:
        raise ValueError('tz-aware dtype conflicts with explicit tz=None')
    return tz or dt_tz

Prevention

When it happens

Trigger: pd.DatetimeIndex(data, dtype='datetime64[ns, UTC]', tz=None); a wrapper that always forwards tz=None as a default colliding with a tz-aware dtype.

Common situations: API defaults where tz=None means 'no preference' but the dtype already encodes a tz; mixing legacy code that passes tz=None with new dtype-aware code.

Related errors


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