{"record":{"id":"43021e75a4f0f5b4","repo":"pandas-dev/pandas","slug":"cannot-convert-tz-naive-timestamps-use-tz-localiz","errorCode":null,"errorMessage":"Cannot convert tz-naive timestamps, use tz_localize to localize","messagePattern":"Cannot convert tz-naive timestamps, use tz_localize to localize","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"pandas/core/arrays/arrow/array.py","lineNumber":4279,"sourceCode":"            \"shift_backward\": \"earliest\",\n            \"shift_forward\": \"latest\",\n        }.get(\n            nonexistent,  # type: ignore[arg-type]\n            None,\n        )\n        if nonexistent_pa is None:\n            raise NotImplementedError(f\"{nonexistent=} is not supported\")\n        if tz is None:\n            result = pc.local_timestamp(self._pa_array)\n        else:\n            result = pc.assume_timezone(\n                self._pa_array, str(tz), ambiguous=ambiguous, nonexistent=nonexistent_pa\n            )\n        return self._from_pyarrow_array(result)\n\n    def _dt_tz_convert(self, tz) -> Self:\n        if self.dtype.pyarrow_dtype.tz is None:\n            raise TypeError(\n                \"Cannot convert tz-naive timestamps, use tz_localize to localize\"\n            )\n        current_unit = self.dtype.pyarrow_dtype.unit\n        result = self._pa_array.cast(pa.timestamp(current_unit, tz))\n        return self._from_pyarrow_array(result)\n\n\ndef transpose_homogeneous_pyarrow(\n    arrays: Sequence[ArrowExtensionArray],\n) -> list[ArrowExtensionArray]:\n    \"\"\"Transpose arrow extension arrays in a list, but faster.\n\n    Input should be a list of arrays of equal length and all have the same\n    dtype. The caller is responsible for ensuring validity of input data.\n    \"\"\"\n    arrays = list(arrays)\n    nrows, ncols = len(arrays[0]), len(arrays)\n    indices = np.arange(nrows * ncols).reshape(ncols, nrows).T.reshape(-1)","sourceCodeStart":4261,"sourceCodeEnd":4297,"githubUrl":"https://github.com/pandas-dev/pandas/blob/71959b8cb9b2459c16e14b34f28b178ccfe14735/pandas/core/arrays/arrow/array.py#L4261-L4297","documentation":"Raised by ArrowExtensionArray._dt_tz_convert when the Series timestamps are tz-naive (pyarrow timestamp type has tz=None). tz_convert requires an existing timezone to convert from; you must first localize naive timestamps. Raised as TypeError and reached through Series.dt.tz_convert() on a tz-naive timestamp[pyarrow] Series.","triggerScenarios":"Calling `s.dt.tz_convert(\"UTC\")` on a Series whose dtype is `timestamp[us][pyarrow]` with no tz. Common after loading Parquet/Arrow data that stored timezone-naive timestamps.","commonSituations":"Assuming a column is tz-aware when it is actually naive; chaining tz_convert where tz_localize was needed; data ingestion stripping tz metadata.","solutions":["Localize first: `s.dt.tz_localize(\"UTC\").dt.tz_convert(\"US/Eastern\")`.","Check `s.dtype.pyarrow_dtype.tz` before calling tz_convert; if None, call tz_localize instead.","Load the data with explicit tz: parse with `pd.to_datetime(s, utc=True)` if source is UTC.","Use `s.dt.tz` (None for naive) as a guard in pipeline code."],"exampleFix":"# before\ns = pd.Series(..., dtype=\"timestamp[us][pyarrow]\")  # tz-naive\ns.dt.tz_convert(\"UTC\")  # TypeError\n\n# after\ns.dt.tz_localize(\"UTC\").dt.tz_convert(\"US/Eastern\")","handlingStrategy":"type-guard","validationCode":"def is_tz_aware_pyarrow(s) -> bool:\n    pa_dt = getattr(s.dtype, \"pyarrow_dtype\", None)\n    return pa_dt is not None and getattr(pa_dt, \"tz\", None) is not None\n\ndef safe_tz_convert(s, tz):\n    if not is_tz_aware_pyarrow(s):\n        raise TypeError(\"Series is tz-naive; call tz_localize(tz) first\")\n    return s.dt.tz_convert(tz)","typeGuard":"import pyarrow as pa\n\ndef is_tz_aware_pyarrow(s) -> bool:\n    pa_dt = getattr(s.dtype, \"pyarrow_dtype\", None)\n    return pa_dt is not None and pa.types.is_timestamp(pa_dt) and pa_dt.tz is not None","tryCatchPattern":"try:\n    out = s.dt.tz_convert(tz)\nexcept TypeError:\n    out = s.dt.tz_localize(\"UTC\").dt.tz_convert(tz)","preventionTips":["Check s.dtype.pyarrow_dtype.tz before tz_convert; None means call tz_localize instead.","Load timestamp data with explicit tz (e.g. pd.to_datetime(s, utc=True)).","Document localize-vs-convert decision in ETL helpers."],"tags":["pyarrow","datetime-accessor","timezone","type-error"],"analyzedSha":"71959b8cb9b2459c16e14b34f28b178ccfe14735","analyzedAt":"2026-08-07T01:30:20.476Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}