{"record":{"id":"6d361297cfe1c57b","repo":"python/cpython","slug":"invalid-iso-string","errorCode":null,"errorMessage":"Invalid ISO string","messagePattern":"Invalid ISO string","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/_pydatetime.py","lineNumber":314,"sourceCode":"\n# Helpers for parsing the result of isoformat()\ndef _is_ascii_digit(c):\n    return c in \"0123456789\"\n\ndef _find_isoformat_datetime_separator(dtstr):\n    # See the comment in _datetimemodule.c:_find_isoformat_datetime_separator\n    len_dtstr = len(dtstr)\n    if len_dtstr == 7:\n        return 7\n\n    assert len_dtstr > 7\n    date_separator = \"-\"\n    week_indicator = \"W\"\n\n    if dtstr[4] == date_separator:\n        if dtstr[5] == week_indicator:\n            if len_dtstr < 8:\n                raise ValueError(\"Invalid ISO string\")\n            if len_dtstr > 8 and dtstr[8] == date_separator:\n                if len_dtstr == 9:\n                    raise ValueError(\"Invalid ISO string\")\n                if len_dtstr > 10 and _is_ascii_digit(dtstr[10]):\n                    # This is as far as we need to resolve the ambiguity for\n                    # the moment - if we have YYYY-Www-##, the separator is\n                    # either a hyphen at 8 or a number at 10.\n                    #\n                    # We'll assume it's a hyphen at 8 because it's way more\n                    # likely that someone will use a hyphen as a separator than\n                    # a number, but at this point it's really best effort\n                    # because this is an extension of the spec anyway.\n                    # TODO(pganssle): Document this\n                    return 8\n                return 10\n            else:\n                # YYYY-Www (8)\n                return 8","sourceCodeStart":296,"sourceCodeEnd":332,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pydatetime.py#L296-L332","documentation":"Raised while locating the date/time separator in an ISO 8601 string during datetime.fromisoformat (the pure-Python fallback path _find_isoformat_datetime_separator). It fires for week-date strings of the form YYYY-Www that are truncated at exactly 8 characters or shorter where a separator must follow, i.e. structurally ambiguous/malformed week-date prefixes such as '2021-W53-' (length 9) or strings cut at the week number where the parser still expects a day component separator.","triggerScenarios":"datetime.fromisoformat('2021-W53-') (len 9 after the W-branch); week-date strings shorter than 8 chars once a 'W' at index 5 is seen; hand-built 'YYYY-Www' + partial separator strings passed to fromisoformat.","commonSituations":"Parsing truncated logs or user input that was sliced mid-timestamp; feeding ISO week-date strings (which fromisoformat only supports partially and version-dependently) from calendar.ISO calendars; strings produced by string concatenation of date parts with a trailing hyphen.","solutions":["Validate/complete the timestamp before parsing: ISO week dates should be fully formed like '2021-W53-5' or use date.fromisocalendar(2021, 53, 5) instead of fromisoformat","Strip trailing separators: s.rstrip('-') then re-check format","Parse with a strict schema first (e.g. datetime.strptime(s, '%G-W%V-%u')) and fall back to fromisoformat"],"exampleFix":"// before\ndt = datetime.fromisoformat('2021-W53-')  # ValueError\n\n# after\nfrom datetime import date\nd = date.fromisocalendar(2021, 53, 5)","handlingStrategy":"validation","validationCode":"import re\n_ISO_WEEK_RE = re.compile(r'^\\d{4}-W\\d{2}-\\d$')\ndef parse_week_date(s: str):\n    if not _ISO_WEEK_RE.fullmatch(s):\n        raise ValueError(f'not a complete ISO week date: {s!r}')\n    return datetime.fromisoformat(s)","typeGuard":"def is_complete_iso_week_date(s: str) -> bool:\n    return len(s) == 10 and s[4] == '-' and s[5] == 'W' and s[8] == '-'","tryCatchPattern":"try:\n    dt = datetime.fromisoformat(s)\nexcept ValueError:\n    dt = None  # log and skip malformed record","preventionTips":["Never feed truncated/sliced timestamps to fromisoformat","Use date.fromisocalendar for week dates instead of string parsing","Validate extracted substrings before parsing"],"tags":["datetime","isoformat","fromisoformat","iso-week","valueerror","stdlib"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}