dgtlmoon/changedetection.io · warning · ValueError
Invalid time_str: '{time_str}'. Must be in 'HH:MM' format.
Error message
Invalid time_str: '{time_str}'. Must be in 'HH:MM' format. What it means
ValueError raised by am_i_inside_time when time_str cannot be parsed as HH:MM: the split(':') + int() conversion fails, or the parsed hour/minute are out of range (hour 0-23, minute 0-59). AttributeError is also caught, so a non-string time_str (None, int) triggers the same message.
Source
Thrown at changedetectionio/time_handler.py:47
timezone_str (str): The timezone identifier (e.g., 'Europe/Berlin').
duration (int, optional): The duration of the time range in minutes. Default is 15.
Returns:
bool: True if the current time is within the time range, False otherwise.
"""
# Parse the target day of the week
try:
target_weekday = Weekday[day_of_week.capitalize()]
except KeyError:
raise ValueError(f"Invalid day_of_week: '{day_of_week}'. Must be a valid weekday name.")
# Parse the start time
try:
hour, minute = map(int, time_str.split(':'))
if not (0 <= hour <= 23 and 0 <= minute <= 59):
raise ValueError
except (ValueError, AttributeError):
raise ValueError(f"Invalid time_str: '{time_str}'. Must be in 'HH:MM' format.")
# Get the current time in the specified timezone
try:
now_tz = arrow.now(timezone_str.strip())
except Exception as e:
raise ValueError(f"Invalid timezone_str: '{timezone_str}'. Must be a valid timezone identifier.")
# Check if the current day matches the target day or overlaps due to duration
current_weekday = now_tz.weekday()
# Create start datetime for today in target timezone
start_datetime_tz = now_tz.replace(hour=hour, minute=minute, second=0, microsecond=0)
# Handle previous day's overlap
if target_weekday == (current_weekday - 1) % 7:
# Calculate start and end times for the overlap from the previous day
start_datetime_tz = start_datetime_tz.shift(days=-1)
end_datetime_tz = start_datetime_tz.shift(minutes=duration)
if start_datetime_tz <= now_tz <= end_datetime_tz:View on GitHub (pinned to 5d9c7c6da7)
Solutions
- Format times as zero-padded 24-hour 'HH:MM' (e.g. '09:30', '23:59')
- Validate with a regex like ^([01]?\d|2[0-3]):[0-5]\d$ before storing/submitting
- Convert AM/PM input to 24h format in your integration layer
- Reject schedule settings early in your UI/API with a clear message instead of letting am_i_inside_time throw
Example fix
# before
am_i_inside_time('monday', '9:30 AM', '1', 'utc')
# after
am_i_inside_time('monday', '09:30', '1', 'utc') Defensive patterns
Strategy: validation
Validate before calling
import re
if not re.fullmatch(r'([01]?\d|2[0-3]):[0-5]\d', time_str or ''):
raise ValueError('time must be HH:MM 24h') Type guard
import re
def is_valid_hhmm(s: str) -> bool:
return bool(re.fullmatch(r'([01]?\d|2[0-3]):[0-5]\d', s or '')) Try / catch
try:
inside = am_i_inside_time(day, time_str, duration, tz)
except ValueError as e:
return bad_request(str(e)) # distinguishes day/time/timezone in message Prevention
- Always submit zero-padded 24h times; convert AM/PM client-side
- Validate schedule JSON before writing it to a watch
- Use HTML input type="time" in UIs to guarantee HH:MM format
When it happens
Trigger: Calling am_i_inside_time with time_str like '9:0:0', '0900', '25:00', '12:5pm', None, or 900 (int). Any deviation from exactly two colon-separated integers in valid range raises.
Common situations: Schedule forms filled with 24h+ formats or AM/PM text; scripts building 'HH:MM' with f-strings that omit zero-padding ('9:5' is actually fine — int() handles it — but '9' alone fails); users copying times from locales using '.' or ',' separators ('09.30').
Related errors
- Invalid day_of_week: '{day_of_week}'. Must be a valid weekda
- Invalid timezone_str: '{timezone_str}'. Must be a valid time
- "{}" is not a valid bool value
AI-assisted analysis of dgtlmoon/changedetection.io@5d9c7c6da7 (2026-08-27).
Data as JSON: /api/errors/0c4cf72e5d3c4de0.
Report an issue: GitHub.