python/cpython · error · ValueError
Minute, second, and microsecond must be 0 when hour is 24
Error message
Minute, second, and microsecond must be 0 when hour is 24
What it means
Raised by time.fromisoformat() when the string uses hour 24 (ISO 8601 permits 24:00:00 to mean midnight at the end of a day) but minute, second, or microsecond are non-zero. The parser accepts hour 24 only for the exact end-of-day value; any additional time components make the value ambiguous/invalid, so a dedicated ValueError (instead of the generic 'Invalid isoformat string') is raised.
Source
Thrown at Lib/_pydatetime.py:1656
raise TypeError('fromisoformat: argument must be str')
# The spec actually requires that time-only ISO 8601 strings start with
# T, but the extended format allows this to be omitted as long as there
# is no ambiguity with date strings.
time_string = time_string.removeprefix('T')
try:
time_components, _, error_from_components, error_from_tz = (
_parse_isoformat_time(time_string)
)
except ValueError:
raise ValueError(
f'Invalid isoformat string: {time_string!r}') from None
else:
if error_from_tz:
raise error_from_tz
if error_from_components:
raise ValueError(
"Minute, second, and microsecond must be 0 when hour is 24"
)
return cls(*time_components)
def strftime(self, format):
"""Format using strftime(). The date part of the timestamp passed
to underlying strftime should not be used.
For a list of supported format codes, see the documentation:
https://docs.python.org/3/library/datetime.html#format-codes
"""
# The year must be >= 1000 else Python's strftime implementation
# can raise a bogus exception.
timetuple = (1900, 1, 1,
self._hour, self._minute, self._second,
0, 1, -1)
return _wrap_strftime(self, format, timetuple)View on GitHub (pinned to bc6749cc3b)
Solutions
- Parse durations as timedelta, not time: convert '24:30:00' by splitting components into timedelta(hours=24, minutes=30)
- If the value is genuinely end-of-day, use exactly '24:00:00' or normalize to time(0,0)
- Validate hour<24 (or ==24 with zero remainder) before calling fromisoformat
Example fix
# before
t = time.fromisoformat('24:30:00') # ValueError
# after
from datetime import timedelta
h, m, s = map(int, '24:30:00'.split(':'))
d = timedelta(hours=h, minutes=m, seconds=s) Defensive patterns
Strategy: validation
Validate before calling
def parse_hour24(s: str):
h, rest = int(s[0:2]), s[2:]
if h == 24 and rest not in (':00:00', ':00:00.000000', ''):
raise ValueError('hour 24 requires zero minutes/seconds/microseconds')
return time.fromisoformat(s) if h < 24 else time(0, 0) Type guard
def is_duration_like(s: str) -> bool:
return int(s[0:2]) >= 24 Try / catch
try:
t = time.fromisoformat(s)
except ValueError as e:
if 'hour is 24' in str(e):
h, m, sec = map(int, s.split(':'))
t = timedelta(hours=h, minutes=m, seconds=sec) # reinterpret as duration
else:
raise Prevention
- Model elapsed/overnight values as timedelta, never time
- Validate hour <= 23 (or exactly 24:00:00) in ingestion schemas
- Reject or remap 24:xx strings from external feeds before they reach parsers
When it happens
Trigger: time.fromisoformat('24:00:01'); time.fromisoformat('24:15:00'); time.fromisoformat('24:00:00.000001'); data feeds that compute durations as hours and emit 24:xx when a task crosses midnight.
Common situations: Duration-like 'HH:MM:SS' strings fed to a time parser — 25+ hours or 24:30 from overnight shifts, media timestamps, or elapsed-time reports; duration fields mis-modeled as clock times.
Related errors
- Invalid isoformat string: {time_string!r}
- Invalid ISO string
- Invalid isoformat string
- Inconsistent use of dash separator
- Incomplete time component
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/02a16e7d242cb2f5.
Report an issue: GitHub.