pandas-dev/pandas · error · NotImplementedError

{nonexistent=} is not supported

Error message

{nonexistent=} is not supported

What it means

Raised by ArrowExtensionArray._dt_tz_localize when `nonexistent` is not one of the three mapped values. The pyarrow backend supports only 'raise', 'shift_backward' (mapped to pyarrow 'earliest'), and 'shift_forward' (mapped to 'latest'). Any other value ('NaT', timedelta like '1h', 'shift') triggers NotImplementedError.

Source

Thrown at pandas/core/arrays/arrow/array.py:4268

    def _dt_tz_localize(
        self,
        tz,
        ambiguous: TimeAmbiguous = "raise",
        nonexistent: TimeNonexistent = "raise",
    ) -> Self:
        if ambiguous != "raise":
            raise NotImplementedError(f"{ambiguous=} is not supported")
        nonexistent_pa = {
            "raise": "raise",
            "shift_backward": "earliest",
            "shift_forward": "latest",
        }.get(
            nonexistent,  # type: ignore[arg-type]
            None,
        )
        if nonexistent_pa is None:
            raise NotImplementedError(f"{nonexistent=} is not supported")
        if tz is None:
            result = pc.local_timestamp(self._pa_array)
        else:
            result = pc.assume_timezone(
                self._pa_array, str(tz), ambiguous=ambiguous, nonexistent=nonexistent_pa
            )
        return self._from_pyarrow_array(result)

    def _dt_tz_convert(self, tz) -> Self:
        if self.dtype.pyarrow_dtype.tz is None:
            raise TypeError(
                "Cannot convert tz-naive timestamps, use tz_localize to localize"
            )
        current_unit = self.dtype.pyarrow_dtype.unit
        result = self._pa_array.cast(pa.timestamp(current_unit, tz))
        return self._from_pyarrow_array(result)

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Use one of the supported values: 'raise' (default), 'shift_forward', or 'shift_backward'.
  2. Cast to datetime64[ns] for richer nonexistent handling: `s.astype("datetime64[ns]").dt.tz_localize("US/Eastern", nonexistent="NaT")`.
  3. Filter out times in the gap before localizing with nonexistent='raise'.
  4. Localize to UTC first if exact wall-clock mapping is not required.

Example fix

# before
s.dt.tz_localize("US/Eastern", nonexistent="NaT")  # NotImplementedError

# after
out = s.astype("datetime64[ns]").dt.tz_localize("US/Eastern", nonexistent="NaT")
Defensive patterns

Strategy: validation

Validate before calling

SUPPORTED_NONEXISTENT = {"raise", "shift_forward", "shift_backward"}

def safe_tz_localize(s, tz, ambiguous="raise"):
    if nonexistent not in SUPPORTED_NONEXISTENT:
        return s.astype("datetime64[ns]").dt.tz_localize(tz, ambiguous=ambiguous, nonexistent=nonexistent)
    return s.dt.tz_localize(tz, ambiguous=ambiguous, nonexistent=nonexistent)

Type guard

def is_supported_nonexistent(v) -> bool:
    return v in {"raise", "shift_forward", "shift_backward"}

Try / catch

try:
    out = s.dt.tz_localize(tz, nonexistent=nonexistent)
except NotImplementedError:
    out = s.astype("datetime64[ns]").dt.tz_localize(tz, nonexistent=nonexistent)

Prevention

When it happens

Trigger: Calling `s.dt.tz_localize("US/Eastern", nonexistent="NaT")` or `nonexistent=pd.Timedelta("1h")` on a tz-naive pyarrow timestamp Series whose times fall in a DST spring-forward gap. Reached via dt.tz_localize on timestamp[pyarrow].

Common situations: Localizing data into a DST timezone during spring-forward; wanting NaT fill for nonexistent times; porting localize code from numpy backend that supported more nonexistent strategies.

Related errors


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