{"record":{"id":"10eeed4c42c7c3d2","repo":"pandas-dev/pandas","slug":"cannot-supply-both-a-tz-and-a-dtype-with-a-tz","errorCode":null,"errorMessage":"cannot supply both a tz and a dtype with a tz","messagePattern":"cannot supply both a tz and a dtype with a tz","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/datetimes.py","lineNumber":3044,"sourceCode":"\n    Raises\n    ------\n    ValueError : on tzinfo mismatch\n    \"\"\"\n    if dtype is not None:\n        if isinstance(dtype, str):\n            try:\n                dtype = DatetimeTZDtype.construct_from_string(dtype)\n            except TypeError:\n                # Things like `datetime64[ns]`, which is OK for the\n                # constructors, but also nonsense, which should be validated\n                # but not by us. We *do* allow non-existent tz errors to\n                # go through\n                pass\n        dtz = getattr(dtype, \"tz\", None)\n        if dtz is not None:\n            if tz is not None and not timezones.tz_compare(tz, dtz):\n                raise ValueError(\"cannot supply both a tz and a dtype with a tz\")\n            if explicit_tz_none:\n                raise ValueError(\"Cannot pass both a timezone-aware dtype and tz=None\")\n            tz = dtz\n\n        if tz is not None and lib.is_np_dtype(dtype, \"M\"):\n            # We also need to check for the case where the user passed a\n            #  tz-naive dtype (i.e. datetime64[ns])\n            if tz is not None and not timezones.tz_compare(tz, dtz):\n                raise ValueError(\n                    \"cannot supply both a tz and a \"\n                    \"timezone-naive dtype (i.e. datetime64[ns])\"\n                )\n\n    return tz\n\n\ndef _infer_tz_from_endpoints(\n    start: Timestamp, end: Timestamp, tz: tzinfo | None","sourceCodeStart":3026,"sourceCodeEnd":3062,"githubUrl":"https://github.com/pandas-dev/pandas/blob/3b7651241d4da534b3559b60ef128e1c34f54116/pandas/core/arrays/datetimes.py#L3026-L3062","documentation":"Raised by _validate_tz_from_dtype when a tz argument is supplied AND the dtype itself carries a tz (DatetimeTZDtype) AND the two disagree per timezones.tz_compare. The function refuses to silently prefer one over the other; you must reconcile them. Note this branch checks `dtz is not None` (dtype has tz) and the conflict is between the kwarg tz and the dtype tz.","triggerScenarios":"Calling `pd.DatetimeIndex(values, dtype='datetime64[ns, US/Eastern]', tz='US/Pacific')` — both channels specify a tz and they differ. Constructing a Series/Index where the dtype string embeds one tz and a separate tz kwarg supplies another.","commonSituations":"Building dtype strings dynamically and also passing a tz kwarg as a 'safety net'. Refactoring that left both forms in place. Mixing a hardcoded tz kwarg with a parameterized dtype string.","solutions":["Supply the tz through exactly one channel: either embed it in the dtype string OR pass it as the tz kwarg, not both.","If both are needed by API contract, ensure they agree: `assert tz is None or tz_compare(tz, dtype.tz)`.","Prefer the tz kwarg and use a tz-naive dtype like 'datetime64[ns]' to avoid duplication."],"exampleFix":"// before\ndti = pd.DatetimeIndex(values, dtype='datetime64[ns, US/Eastern]', tz='US/Pacific')\n\n// after\ndti = pd.DatetimeIndex(values, tz='US/Pacific')","handlingStrategy":"validation","validationCode":"import pandas as pd\n\ndef single_tz_channel(dtype_str, tz):\n    dtz = None\n    if dtype_str:\n        try:\n            d = pd.DatetimeTZDtype.construct_from_string(dtype_str)\n            dtz = getattr(d, 'tz', None)\n        except TypeError:\n            pass\n    if dtz is not None and tz is not None:\n        return dtype_str, None  # prefer dtype, drop tz kwarg\n    return dtype_str, tz","typeGuard":"def tz_channels_agree(dtype_str, tz) -> bool:\n    import pandas as pd\n    dtz = None\n    if dtype_str:\n        try:\n            d = pd.DatetimeTZDtype.construct_from_string(dtype_str)\n            dtz = getattr(d, 'tz', None)\n        except TypeError:\n            pass\n    if dtz is None or tz is None:\n        return True\n    return pd.core.dtypes.common.timezones.tz_compare(dtz, tz)","tryCatchPattern":"try:\n    dti = pd.DatetimeIndex(values, dtype=dtype_str, tz=tz)\nexcept ValueError as e:\n    if 'cannot supply both a tz and a dtype' in str(e):\n        dti = pd.DatetimeIndex(values, tz=tz)\n    else:\n        raise","preventionTips":["Pass tz through exactly one channel — either embed in dtype or as kwarg.","In library wrappers, default the unused channel to None and document."],"tags":["datetime","timezone","dtype","construction","validation"],"backgroundTag":null,"analyzedSha":"3b7651241d4da534b3559b60ef128e1c34f54116","analyzedAt":"2026-08-11T22:10:44.015Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}