{"record":{"id":"5c147b40f8e71a62","repo":"python/cpython","slug":"invalid-isoformat-string-time-string-r","errorCode":null,"errorMessage":"Invalid isoformat string: {time_string!r}","messagePattern":"Invalid isoformat string: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/_pydatetime.py","lineNumber":1650,"sourceCode":"    __str__ = isoformat\n\n    @classmethod\n    def fromisoformat(cls, time_string):\n        \"\"\"Construct a time from a string in one of the ISO 8601 formats.\"\"\"\n        if not isinstance(time_string, str):\n            raise TypeError('fromisoformat: argument must be str')\n\n        # The spec actually requires that time-only ISO 8601 strings start with\n        # T, but the extended format allows this to be omitted as long as there\n        # is no ambiguity with date strings.\n        time_string = time_string.removeprefix('T')\n\n        try:\n            time_components, _, error_from_components, error_from_tz = (\n                _parse_isoformat_time(time_string)\n            )\n        except ValueError:\n            raise ValueError(\n                f'Invalid isoformat string: {time_string!r}') from None\n        else:\n            if error_from_tz:\n                raise error_from_tz\n            if error_from_components:\n                raise ValueError(\n                    \"Minute, second, and microsecond must be 0 when hour is 24\"\n                )\n\n            return cls(*time_components)\n\n    def strftime(self, format):\n        \"\"\"Format using strftime().  The date part of the timestamp passed\n        to underlying strftime should not be used.\n\n        For a list of supported format codes, see the documentation:\n            https://docs.python.org/3/library/datetime.html#format-codes\n        \"\"\"","sourceCodeStart":1632,"sourceCodeEnd":1668,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pydatetime.py#L1632-L1668","documentation":"Raised by time.fromisoformat() when _parse_isoformat_time cannot parse the string as an ISO 8601 time. The original lower-level ValueError is suppressed (`from None`) and replaced with this message echoing the offending string, so the repr of the bad input is visible in the traceback. Common causes are stray characters, wrong separators, or invalid component values.","triggerScenarios":"time.fromisoformat('12.30.00') (dots instead of colons); time.fromisoformat('25:00') (hour out of range); time.fromisoformat('12:30:00 UTC') (trailing junk); time.fromisoformat('2024-01-01') (a date, not a time); time.fromisoformat('') (empty string).","commonSituations":"User-supplied 'HH:MM' input forms (these are valid), but variants like '12 noon', 'h12:30', or locale-formatted times are not; concatenating date and time without the separator; whitespace not stripped; CSV/Excel exports with non-ISO times like '1:30 PM'.","solutions":["Normalize the input before parsing: strip whitespace, convert 12-hour AM/PM to 24-hour, replace '.' time separators with ':'","Use dateutil.parser.parse or a targeted strptime format for non-ISO inputs: datetime.strptime(s, '%I:%M %p').time()","For free-form fields, validate with a regex (e.g. ^\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?$) before calling fromisoformat"],"exampleFix":"# before\nt = time.fromisoformat('1:30 PM')\n\n# after\nfrom datetime import datetime\nt = datetime.strptime('1:30 PM', '%I:%M %p').time()","handlingStrategy":"validation","validationCode":"import re\nISO_TIME = re.compile(r'^\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?(Z|[+-]\\d{2}:?\\d{2})?$')\ns = s.strip()\nif not ISO_TIME.match(s):\n    raise ValueError(f'not an ISO time: {s!r}')\nt = time.fromisoformat(s)","typeGuard":"def looks_like_iso_time(s: str) -> bool:\n    return bool(re.match(r'^\\d{2}:\\d{2}(:\\d{2}(\\.\\d{1,6})?)?$', s))","tryCatchPattern":"try:\n    t = time.fromisoformat(s)\nexcept ValueError:\n    t = datetime.strptime(s.strip(), '%I:%M %p').time()  # known fallback format","preventionTips":["Strip whitespace and normalize separators before parsing","Constrain user input with a regex or input mask at the form layer","Route non-ISO formats (AM/PM, locale variants) to strptime or dateutil explicitly"],"tags":["datetime","time","valueerror","fromisoformat","parsing"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}