pandas-dev/pandas · error · ValueError

Passed data is timezone-aware, incompatible with 'tz=None'…

Error message

Passed data is timezone-aware, incompatible with 'tz=None'. Use obj.tz_localize(None) instead.

What it means

Raised by DatetimeArray._sequence_to_dt64 path when the supplied data is timezone-aware (a tz was inferred or present) but the caller explicitly requested tz=None. tz=None is ambiguous here — it could mean 'drop tz' or 'no tz expected' — so pandas makes the user choose with tz_localize(None), avoiding silent data loss.

Solutions

  1. Drop the timezone intentionally: obj.tz_localize(None) before construction.
  2. Preserve the timezone by passing the correct tz= explicitly.
  3. If you want naive UTC values, obj.tz_convert('UTC').tz_localize(None).

Example fix

// before
aware = pd.Series(pd.to_datetime(['2020-01-01']).tz_localize('UTC'))
pd.DatetimeIndex(aware, tz=None)  # ValueError: tz-aware incompatible with tz=None

// after
pd.DatetimeIndex(aware).tz_localize(None)  # explicitly drop tz
Defensive patterns

Strategy: validation

Validate before calling

def build_index(values, tz=None):
    inferred_tz = getattr(values.dtype, "tz", None)
    if inferred_tz is not None and tz is None:
        raise ValueError("data is tz-aware; call tz_localize(None) to drop")
    return pd.DatetimeIndex(values, tz=tz)

Type guard

def is_tz_aware(values) -> bool:
    return getattr(getattr(values, "dtype", None), "tz", None) is not None

Try / catch

try:
    idx = pd.DatetimeIndex(aware, tz=None)
except ValueError as e:
    if "tz=None" in str(e):
        idx = pd.DatetimeIndex(aware).tz_localize(None)
    else:
        raise

Prevention

When it happens

Trigger: pd.DatetimeIndex(tz_aware_series, tz=None); pd.to_datetime(tz_aware_values, tz=None) is not the trigger here, but internal/array construction with explicit_tz_none=True against tz-aware data is; constructing Series/Index where the dtype or call signature forces tz=None.

Common situations: Passing an already-localized column into a constructor that defaults tz to None; refactoring code that previously used the old silent-drop behavior; mixing tz-aware sources in a pipeline that explicitly nulls tz.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/603519693106c30e. Report an issue: GitHub.

Appendix: source

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

            unit = dtl.dtype_to_unit(dtype)

        data, copy = dtl.ensure_arraylike_for_datetimelike(
            data, copy, cls_name="DatetimeArray"
        )

        subarr, tz = _sequence_to_dt64(
            data,
            copy=copy,
            tz=tz,
            dayfirst=dayfirst,
            yearfirst=yearfirst,
            ambiguous=ambiguous,
            out_unit=unit,
        )
        # We have to call this again after possibly inferring a tz above
        _validate_tz_from_dtype(dtype, tz, explicit_tz_none)
        if tz is not None and explicit_tz_none:
            raise ValueError(
                "Passed data is timezone-aware, incompatible with 'tz=None'. "
                "Use obj.tz_localize(None) instead."
            )

        data_unit = np.datetime_data(subarr.dtype)[0]
        data_unit = cast("TimeUnit", data_unit)
        data_dtype = tz_to_dtype(tz, data_unit)
        result = cls._simple_new(subarr, dtype=data_dtype)
        if unit is not None and unit != result.unit:
            # If unit was specified in user-passed dtype, cast to it here
            # error: Argument 1 to "as_unit" of "TimelikeOps" has
            # incompatible type "str"; expected "Literal['s', 'ms', 'us', 'ns']"
            # [arg-type]
            result = result.as_unit(unit)  # type: ignore[arg-type]

        return result

    @classmethod

View on GitHub (pinned to 3b7651241d)