ZhuLinsen/daily_stock_analysis · error · ValueError
NOTIFICATION_QUIET_HOURS must be in HH:MM-HH:MM format
Error message
NOTIFICATION_QUIET_HOURS must be in HH:MM-HH:MM format
What it means
ValueError from parse_notification_quiet_hours when the NOTIFICATION_QUIET_HOURS environment value does not match the strict HH:MM-HH:MM pattern (24-hour clock). The value must be two zero-padded times joined by a single hyphen; anything else — missing hyphen, 12-hour times, seconds, non-numeric parts — is rejected at config load.
Source
Thrown at src/notification_noise.py:106
def normalize_notification_severity(route_type: Optional[str], severity: Optional[str] = None) -> str:
"""Normalize explicit severity, or derive a default from route type."""
explicit = str(severity or "").strip().lower()
if explicit in NOTIFICATION_SEVERITY_RANK:
return explicit
route = str(route_type or "").strip().lower()
return DEFAULT_NOTIFICATION_SEVERITY_BY_ROUTE.get(route, "info")
def parse_notification_quiet_hours(value: Optional[str]) -> Optional[Tuple[int, int]]:
"""Parse ``HH:MM-HH:MM`` into start/end minute-of-day values."""
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
View on GitHub (pinned to 5159bd72e8)
Solutions
- Use exact zero-padded 24-hour format, e.g. NOTIFICATION_QUIET_HOURS=22:00-06:00
- Remove spaces around the hyphen and any seconds/trailing components
- Unset the variable entirely if you do not want quiet hours — empty is valid and disables the feature
- Check for invisible characters (smart quotes, non-breaking spaces) after pasting into .env
Example fix
# before NOTIFICATION_QUIET_HOURS=10pm - 6am # after NOTIFICATION_QUIET_HOURS=22:00-06:00
Defensive patterns
Strategy: validation
Validate before calling
import re
_QUIET = re.compile(r"^([01]\d|2[0-3]):([0-5]\d)-([01]\d|2[0-3]):([0-5]\d)$")
def is_valid_quiet_hours(value: str) -> bool:
return bool(_QUIET.match((value or "").strip())) Try / catch
try:
quiet = parse_notification_quiet_hours(os.getenv("NOTIFICATION_QUIET_HOURS"))
except ValueError as exc:
log.error("Config error: %s (expected HH:MM-HH:MM, e.g. 22:00-06:00)", exc)
raise SystemExit(2) Prevention
- Show the expected format in .env.example comments
- Validate notification config at startup, not on first notification
- Prefer unset (disabled) over malformed values in generated configs
When it happens
Trigger: Setting NOTIFICATION_QUIET_HOURS to values like '22:00', '22:00 - 06:00' (spaces), '9pm-6am', '22:0-06:00', '22:00-06:00:30', or '22-06'. Only strings fully matching HH:MM-HH:MM with hours 00-23 and minutes 00-59 (per the regex) parse successfully.
Common situations: Hand-editing .env with a human-friendly time range; copying a 12-hour format from documentation of another tool; locale-specific time strings; trailing whitespace or smart quotes after copy-paste from a chat or doc.
Related errors
- unknown timezone: {raw}
- 无效的定时执行时间: {self.schedule_time!r}
- validation_failed
- capability_unsupported
- Responses API surface requires a normalized openai/<model> r
AI-assisted analysis of ZhuLinsen/daily_stock_analysis@5159bd72e8 (2026-08-15).
Data as JSON: /api/errors/73e752296192ed75.
Report an issue: GitHub.