ZhuLinsen/daily_stock_analysis · error · ValueError

zoneinfo is unavailable

Error message

zoneinfo is unavailable

What it means

ValueError from validate_notification_timezone when a NOTIFICATION_TIMEZONE value is supplied but the ZoneInfo class could not be imported in the running interpreter. This is an environment capability failure, not a bad timezone name: the code guards the import and only raises here when a timezone is actually requested while zoneinfo is unavailable.

Source

Thrown at src/notification_noise.py:118

    raw = str(value or "").strip()
    if not raw:
        return None

    match = _QUIET_HOURS_RE.match(raw)
    if not match:
        raise ValueError("NOTIFICATION_QUIET_HOURS must be in HH:MM-HH:MM format")

    start_hour, start_minute, end_hour, end_minute = [int(group) for group in match.groups()]
    return start_hour * 60 + start_minute, end_hour * 60 + end_minute


def validate_notification_timezone(value: Optional[str]) -> None:
    """Validate an optional IANA timezone name."""
    raw = str(value or "").strip()
    if not raw:
        return
    if ZoneInfo is None:
        raise ValueError("zoneinfo is unavailable")
    try:
        ZoneInfo(raw)
    except ZoneInfoNotFoundError as exc:
        raise ValueError(f"unknown timezone: {raw}") from exc


def is_time_in_quiet_hours(now: datetime, quiet_hours: Tuple[int, int]) -> bool:
    """Return whether *now* falls inside a quiet-hours interval."""
    start_minute, end_minute = quiet_hours
    minute_of_day = now.hour * 60 + now.minute

    if start_minute == end_minute:
        return False
    if start_minute < end_minute:
        return start_minute <= minute_of_day < end_minute
    return minute_of_day >= start_minute or minute_of_day < end_minute

View on GitHub (pinned to 5159bd72e8)

Solutions

  1. Upgrade the runtime to Python 3.9 or newer where zoneinfo is in the standard library
  2. Leave NOTIFICATION_TIMEZONE empty/unset — quiet hours then use local time and the import is never required
  3. On custom builds, ensure the stdlib zoneinfo module and tzdata are included in the image
  4. Pin CI/deploy images to python:3.10+ or equivalent

Example fix

# before (python 3.8 runtime, timezone set)
NOTIFICATION_TIMEZONE=Asia/Shanghai

# after
# either run on Python >= 3.9, or unset:
# NOTIFICATION_TIMEZONE=
Defensive patterns

Strategy: validation

Validate before calling

import sys

def zoneinfo_available() -> bool:
    if sys.version_info < (3, 9):
        return False
    try:
        from zoneinfo import ZoneInfo  # noqa: F401
        return True
    except ImportError:
        return False

Try / catch

try:
    validate_notification_timezone(tz)
except ValueError as exc:
    if str(exc) == "zoneinfo is unavailable":
        log.warning("Timezone ignored: needs Python >= 3.9; continuing with local time")
    else:
        raise

Prevention

When it happens

Trigger: Running on Python older than 3.9 (zoneinfo added in 3.9) with NOTIFICATION_TIMEZONE set to a non-empty value, or on a stripped interpreter where the stdlib zoneinfo module was removed. Any non-empty timezone config triggers it.

Common situations: Deploying to a legacy Python 3.8 image; a minimal/alpine-like custom build pruning stdlib modules; a virtualenv built against an old system Python; CI matrix still including EOL Python versions.

Related errors


AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15). Data as JSON: /api/errors/72333746f6da50f9. Report an issue: GitHub.