{"record":{"id":"1ca87d0550a18240","repo":"python/cpython","slug":"year-must-be-in-minyear-maxyear-not-year","errorCode":null,"errorMessage":"year must be in {MINYEAR}..{MAXYEAR}, not {year}","messagePattern":"year must be in (.+?)\\.\\.(.+?), not (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/_pydatetime.py","lineNumber":515,"sourceCode":"                _check_time_fields(hour=tz_comps[0], minute=tz_comps[1],\n                                   second=tz_comps[2], microsecond=tz_comps[3],\n                                   fold=0)\n            except ValueError as e:\n                error_from_tz = e\n            else:\n                td = timedelta(hours=tz_comps[0], minutes=tz_comps[1],\n                               seconds=tz_comps[2], microseconds=tz_comps[3])\n                tzi = timezone(tzsign * td)\n\n    time_comps.append(tzi)\n\n    return time_comps, became_next_day, error_from_components, error_from_tz\n\n# tuple[int, int, int] -> tuple[int, int, int] version of date.fromisocalendar\ndef _isoweek_to_gregorian(year, week, day):\n    # Year is bounded this way because 9999-12-31 is (9999, 52, 5)\n    if not MINYEAR <= year <= MAXYEAR:\n        raise ValueError(f\"year must be in {MINYEAR}..{MAXYEAR}, not {year}\")\n\n    if not 0 < week < 53:\n        out_of_range = True\n\n        if week == 53:\n            # ISO years have 53 weeks in them on years starting with a\n            # Thursday and leap years starting on a Wednesday\n            first_weekday = _ymd2ord(year, 1, 1) % 7\n            if (first_weekday == 4 or (first_weekday == 3 and\n                                       _is_leap(year))):\n                out_of_range = False\n\n        if out_of_range:\n            raise ValueError(f\"Invalid week: {week}\")\n\n    if not 0 < day < 8:\n        raise ValueError(f\"Invalid weekday: {day} (range is [1, 7])\")\n","sourceCodeStart":497,"sourceCodeEnd":533,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pydatetime.py#L497-L533","documentation":"_isoweek_to_gregorian (backing date.fromisocalendar and the ISO-week parse path of fromisoformat) requires the ISO year within datetime.MINYEAR..MAXYEAR (1..9999) because week 1 of an ISO year can resolve into the previous Gregorian year. Out-of-range years raise ValueError with the allowed range echoed.","triggerScenarios":"date.fromisocalendar(0, 1, 1) or (10000, 1, 1); datetime.fromisoformat('10000-W01-1') reaching the week path; user-supplied year 0 from a spreadsheet or form used directly as the ISO year.","commonSituations":"Excel/CSV artifacts exporting year 0 or 1899; two-digit years expanded wrongly ('99' -> 99 not 1999); edge-year tests probing calendar boundaries; default sentinel 0 flowing into fromisocalendar.","solutions":["Clamp or reject years outside 1..9999 before calling fromisocalendar","Fix upstream year expansion (century windowing) so two-digit years map into range","Use try/except ValueError around calendar conversion at the trust boundary and report the bad row/record"],"exampleFix":"// before\nd = date.fromisocalendar(year, week, day)  # year 0 -> ValueError\n\n# after\nif not 1 <= year <= 9999:\n    raise ValueError(f'bad ISO year {year!r} in record')\nd = date.fromisocalendar(year, week, day)","handlingStrategy":"validation","validationCode":"from datetime import MINYEAR, MAXYEAR\ndef check_iso_year(year: int) -> None:\n    if not MINYEAR <= year <= MAXYEAR:\n        raise ValueError(f'ISO year {year} outside {MINYEAR}..{MAXYEAR}')","typeGuard":"def is_valid_iso_year(y: object) -> bool:\n    return isinstance(y, int) and 1 <= y <= 9999","tryCatchPattern":"try:\n    d = date.fromisocalendar(y, w, wd)\nexcept ValueError as e:\n    raise ValueError(f'invalid calendar input {y}/{w}/{wd}: {e}') from e","preventionTips":["Sanitize imported years (0, 1899, 10000 are classic bad data)","Expand two-digit years with an explicit century window","Wrap calendar conversions at the data boundary with row-level error reporting"],"tags":["datetime","isocalendar","fromisocalendar","valueerror","stdlib"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}