python/cpython · error · TypeError

name must be a string

Error message

name must be a string

What it means

When the optional name argument to timezone() is supplied (i.e. not the _Omitted sentinel), it must be a str used as the tzname() display label. Any non-string name — bytes, int, None — raises TypeError. Note None is only legal internally when name was omitted.

Source

Thrown at Lib/_pydatetime.py:2460

    return week1monday


class timezone(tzinfo):
    """Fixed offset from UTC implementation of tzinfo."""

    __slots__ = '_offset', '_name'

    # Sentinel value to disallow None
    _Omitted = object()
    def __new__(cls, offset, name=_Omitted):
        if not isinstance(offset, timedelta):
            raise TypeError("offset must be a timedelta")
        if name is cls._Omitted:
            if not offset:
                return cls.utc
            name = None
        elif not isinstance(name, str):
            raise TypeError("name must be a string")
        if not cls._minoffset <= offset <= cls._maxoffset:
            raise ValueError("offset must be a timedelta "
                             "strictly between -timedelta(hours=24) and "
                             f"timedelta(hours=24), not {offset!r}")
        return cls._create(offset, name)

    def __init_subclass__(cls):
        raise TypeError("type 'datetime.timezone' is not an acceptable base type")

    @classmethod
    def _create(cls, offset, name=None):
        self = tzinfo.__new__(cls)
        self._offset = offset
        self._name = name
        return self

    def __getinitargs__(self):
        """pickle support"""

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Pass a str: timezone(timedelta(hours=-5), 'EST')
  2. To get an auto-derived name (like 'UTC-05:00'), omit the argument entirely
  3. Decode bytes names: name.decode('ascii') before passing
  4. For full IANA names use ZoneInfo('America/New_York')

Example fix

// before
tz = timezone(timedelta(hours=-5), None)

# after
tz = timezone(timedelta(hours=-5))  # name auto-derived
Defensive patterns

Strategy: type-guard

Validate before calling

from datetime import timedelta, timezone

def make_timezone(offset: timedelta, name=None) -> timezone:
    if name is None:
        return timezone(offset)      # omit -> auto-derived name
    if isinstance(name, bytes):
        name = name.decode('ascii')
    return timezone(offset, name)

Type guard

def is_valid_tz_name(name) -> bool:
    return name is None or isinstance(name, str)

Prevention

When it happens

Trigger: timezone(timedelta(hours=-5), b'EST'); timezone(offset, None) explicitly passing None to 'clear' the name; names read from binary config or env vars not decoded.

Common situations: Config keys read as bytes (e.g. os.environb); passing name=None intending auto-generated names — omit the argument instead; copying examples where the name came from a non-str source.

Related errors


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