python/cpython · error · TypeError
fromisoformat: argument must be str
Error message
fromisoformat: argument must be str
What it means
Raised by time.fromisoformat() when the argument is not a str instance. The parser accepts only text in ISO 8601 time formats; bytes, memoryview, or other objects are rejected up front with a TypeError naming the requirement.
Source
Thrown at Lib/_pydatetime.py:1638
The optional argument timespec specifies the number of additional
terms of the time to include. Valid options are 'auto', 'hours',
'minutes', 'seconds', 'milliseconds' and 'microseconds'.
"""
s = _format_time(self._hour, self._minute, self._second,
self._microsecond, timespec)
tz = self._tzstr()
if tz:
s += tz
return s
__str__ = isoformat
@classmethod
def fromisoformat(cls, time_string):
"""Construct a time from a string in one of the ISO 8601 formats."""
if not isinstance(time_string, str):
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(View on GitHub (pinned to bc6749cc3b)
Solutions
- Decode bytes first: time.fromisoformat(raw.decode('utf-8'))
- Skip parsing when the value is already a time instance: isinstance(v, time)
- Guard optional fields: if v is not None: t = time.fromisoformat(v)
Example fix
# before
t = time.fromisoformat(b'12:30:00')
# after
t = time.fromisoformat(b'12:30:00'.decode('ascii')) Defensive patterns
Strategy: type-guard
Validate before calling
if not isinstance(v, str):
if isinstance(v, (bytes, bytearray)):
v = v.decode('utf-8')
elif v is None:
raise ValueError('missing time field')
else:
raise TypeError(f'cannot parse {type(v).__name__} as time')
t = time.fromisoformat(v) Type guard
def is_parseable_str(v) -> bool:
return isinstance(v, str) Try / catch
try:
t = time.fromisoformat(v)
except TypeError:
t = time.fromisoformat(v.decode('utf-8')) # only when bytes was plausible Prevention
- Decode bytes at the I/O boundary
- Skip already-parsed time objects via isinstance checks
- Guard optional fields for None before parsing
When it happens
Trigger: time.fromisoformat(b'12:00:00'); time.fromisoformat(memoryview(b'12:00')); passing a datetime.time object itself; passing None as a default when a config field is missing.
Common situations: Values read from sockets/files as bytes; database or JSON fields already parsed into time objects; optional fields where the caller forwards None instead of skipping the parse.
Related errors
- must be str, not %s
- cannot compare naive and aware times
- Invalid isoformat string: {time_string!r}
- Minute, second, and microsecond must be 0 when hour is 24
- bad tzinfo state arg
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/6a8f34dbdc5f177a.
Report an issue: GitHub.