pandas-dev/pandas · error · ValueError
cannot supply both a tz and a timezone-naive dtype (i.e…
Error message
cannot supply both a tz and a timezone-naive dtype (i.e. datetime64[ns])
What it means
Raised by _validate_tz_from_dtype when a tz kwarg is supplied, the dtype is a numpy datetime64 ('M' kind, hence tz-naive), and the tz disagrees with the (None) dtype tz via timezones.tz_compare. The message names the specific case: the user passed both a tz kwarg and a tz-naive datetime64 dtype. Practically unreachable when tz is None, but fires for any non-None tz paired with a plain datetime64[ns] dtype that should have been a DatetimeTZDtype.
Solutions
- Use a consistent representation: either drop the dtype and pass tz, or use a tz-aware dtype and drop the tz kwarg.
- Prefer `pd.DatetimeIndex(values, tz='UTC')` and let pandas construct the right DatetimeTZDtype.
- If the dtype is fixed upstream, strip the tz kwarg and let the dtype win.
Example fix
// before dti = pd.DatetimeIndex(values, dtype='datetime64[ns]', tz='UTC') // after dti = pd.DatetimeIndex(values, tz='UTC')
Defensive patterns
Strategy: validation
Validate before calling
import pandas as pd, numpy as np
def reconcile_np_m_dtype_with_tz(dtype_str, tz):
if dtype_str and tz is not None:
try:
d = pd.api.types.pandas_dtype(dtype_str)
if isinstance(d, np.dtype) and d.kind == 'M' and getattr(d, 'tz', None) is None:
return None, tz # drop dtype, keep tz kwarg
except TypeError:
pass
return dtype_str, tz Type guard
def no_tz_naive_np_m_with_tz(dtype_str, tz) -> bool:
import numpy as np, pandas as pd
if tz is None or not dtype_str:
return True
try:
d = pd.api.types.pandas_dtype(dtype_str)
except TypeError:
return True
return not (isinstance(d, np.dtype) and d.kind == 'M' and getattr(d, 'tz', None) is None) Try / catch
try:
dti = pd.DatetimeIndex(values, dtype=dtype_str, tz=tz)
except ValueError as e:
if 'timezone-naive dtype' in str(e):
dti = pd.DatetimeIndex(values, tz=tz)
else:
raise Prevention
- When passing tz as a kwarg, omit a tz-naive datetime64 dtype string.
- Use pd.DatetimeTZDtype objects rather than ad-hoc dtype strings when tz matters.
When it happens
Trigger: Calling `pd.DatetimeIndex(values, dtype='datetime64[ns]', tz='UTC')` — the dtype string is tz-naive but a tz kwarg is also given. Functionally pandas will usually reconcile by adopting the tz kwarg, but in the conflict path (mismatched compare) it raises this.
Common situations: Code that simultaneously passes a fixed tz-naive default dtype and a tz kwarg with different intent. Migration where the dtype was hardcoded tz-naive and a tz kwarg was added later.
Related errors
- Cannot pass both a timezone-aware dtype and tz=None
- cannot supply both a tz and a dtype with a tz
- Unexpected value for 'dtype
- Cannot use .astype to convert from timezone-aware dtype to…
- data is already tz-aware
AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11).
Data as JSON: /api/errors/973fe7ffd85a6c3c.
Report an issue: GitHub.
Appendix: source
Thrown at pandas/core/arrays/datetimes.py:3053
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:
"""
If a timezone is not explicitly given via `tz`, see if one can
be inferred from the `start` and `end` endpoints. If more than one
of these inputs provides a timezone, require that they all agree.
Parameters
----------
start : TimestampView on GitHub (pinned to 3b7651241d)