python/cpython · error · TypeError

fromutc() argument must be a datetime instance or None

Error message

fromutc() argument must be a datetime instance or None

What it means

timezone.fromutc(dt) requires its argument to be a datetime instance; None is not accepted here (unlike utcoffset/tzname/dst) because fromutc must perform arithmetic on dt. Strings, dates, or None raise TypeError.

Source

Thrown at Lib/_pydatetime.py:2540

            if self._name is None:
                return self._name_from_offset(self._offset)
            return self._name
        raise TypeError("tzname() argument must be a datetime instance"
                        " or None")

    def dst(self, dt):
        if isinstance(dt, datetime) or dt is None:
            return None
        raise TypeError("dst() argument must be a datetime instance"
                        " or None")

    def fromutc(self, dt):
        if isinstance(dt, datetime):
            if dt.tzinfo is not self:
                raise ValueError("fromutc: dt.tzinfo "
                                 "is not self")
            return dt + self._offset
        raise TypeError("fromutc() argument must be a datetime instance"
                        " or None")

    _maxoffset = timedelta(hours=24, microseconds=-1)
    _minoffset = -_maxoffset

    @staticmethod
    def _name_from_offset(delta):
        if not delta:
            return 'UTC'
        if delta < timedelta(0):
            sign = '-'
            delta = -delta
        else:
            sign = '+'
        hours, rest = divmod(delta, timedelta(hours=1))
        minutes, rest = divmod(rest, timedelta(minutes=1))
        seconds = rest.seconds
        microseconds = rest.microseconds

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Construct the datetime first: tz.fromutc(datetime.fromisoformat(s))
  2. Guard Optional values: if dt is None: skip or default before calling
  3. Use dt.astimezone(tz) on an aware datetime instead of calling fromutc manually

Example fix

// before
local = tz.fromutc(ts)  # ts may be None

# after
if ts is None:
    local = None
else:
    local = tz.fromutc(ts)
Defensive patterns

Strategy: type-guard

Validate before calling

from datetime import datetime

def safe_fromutc(tz, dt: datetime | None):
    if dt is None:
        return None
    if not isinstance(dt, datetime):
        dt = datetime.fromisoformat(str(dt))
    return tz.fromutc(dt)

Type guard

from datetime import datetime

def is_datetime(v) -> bool:
    return isinstance(v, datetime)

Prevention

When it happens

Trigger: tz.fromutc(None); tz.fromutc('2024-01-01T00:00'); tz.fromutc(date(2024,1,1)); generic converters forwarding untyped values.

Common situations: Code paths where a timestamp variable is Optional and None leaks through; parsing pipelines passing raw strings; refactors that changed a datetime parameter into a date.

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/b0d290955db3183b. Report an issue: GitHub.