python/cpython · error · ValueError
Invalid isoformat string
Error message
Invalid isoformat string
What it means
_parse_isoformat_date accepts only date strings of length 7 (YYYY-Www), 8 (YYYYMMDD or YYYY-Www compact variants) or 10 (YYYY-MM-DD). Any other length raises ValueError('Invalid isoformat string') before any digits are inspected, so the content cannot matter yet.
Source
Thrown at Lib/_pydatetime.py:362
if idx < 9:
return idx
if idx % 2 == 0:
# If the index of the last number is even, it's YYYYWwwd
return 7
else:
return 8
else:
# YYYYMMDD (8)
return 8
def _parse_isoformat_date(dtstr):
# It is assumed that this is an ASCII-only string of lengths 7, 8 or 10,
# see the comment on Modules/_datetimemodule.c:_find_isoformat_datetime_separator
if len(dtstr) not in (7, 8, 10):
raise ValueError("Invalid isoformat string")
year = int(dtstr[0:4])
has_sep = dtstr[4] == '-'
pos = 4 + has_sep
if dtstr[pos:pos + 1] == "W":
# YYYY-?Www-?D?
pos += 1
weekno = int(dtstr[pos:pos + 2])
pos += 2
dayno = 1
if len(dtstr) > pos:
if (dtstr[pos:pos + 1] == '-') != has_sep:
raise ValueError("Inconsistent use of dash separator")
pos += has_sep
dayno = int(dtstr[pos:pos + 1])View on GitHub (pinned to bc6749cc3b)
Solutions
- Normalize input to YYYY-MM-DD (or the exact inverse of date.isoformat()) before parsing
- Zero-pad components when constructing strings: f'{y:04d}-{m:02d}-{d:02d}'
- For arbitrary ISO-8601 input use dateutil.parser.isoparse instead of fromisoformat
Example fix
// before d = date.fromisoformat(user_input) # '2021-1-1' -> ValueError # after from datetime import datetime d = datetime.strptime(user_input, '%Y-%m-%d').date()
Defensive patterns
Strategy: validation
Validate before calling
import re
_DATE_RE = re.compile(r'^\d{4}-\d{2}-\d{2}$|^\d{8}$')
def parse_date(s: str):
if not _DATE_RE.fullmatch(s):
raise ValueError(f'expected YYYY-MM-DD or YYYYMMDD, got {s!r}')
return date.fromisoformat(s) Type guard
def looks_like_iso_date(s: str) -> bool:
return len(s) in (8, 10) and s[:4].isdigit() and s.endswith(tuple('0123456789')) Try / catch
try:
d = date.fromisoformat(s)
except ValueError:
d = datetime.strptime(s, '%Y-%m-%d').date() # stricter, better message Prevention
- Remember fromisoformat parses only datetime.isoformat output (pre-3.11), not all of ISO-8601
- Zero-pad generated date strings
- Use dateutil for arbitrary user input
When it happens
Trigger: datetime.fromisoformat('2021-1-1') (length 8 but invalid shape reaches other errors; here e.g. '202101011' length 9, '2021' length 4, '2021-0101' etc.); passing a full datetime string to date.fromisoformat on older Pythons; passing a time-only string like '12:30'.
Common situations: Assuming fromisoformat is a general ISO-8601 parser (it is strict and, pre-3.11, only accepts datetime.isoformat() output); lenient user input with missing zero padding; mixing date.fromisoformat and datetime.fromisoformat on the wrong value.
Related errors
- Invalid ISO string
- Unknown timespec value
- Inconsistent use of dash separator
- Incomplete time component
- Invalid time separator: %c
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/fe165c888dee46e4.
Report an issue: GitHub.