{"record":{"id":"fdd8f99105619fa8","repo":"python/cpython","slug":"minute-must-be-in-0-59-not-minute","errorCode":null,"errorMessage":"minute must be in 0..59, not {minute}","messagePattern":"minute must be in 0\\.\\.59, not (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/_pydatetime.py","lineNumber":589,"sourceCode":"    day = _index(day)\n    if not MINYEAR <= year <= MAXYEAR:\n        raise ValueError(f\"year must be in {MINYEAR}..{MAXYEAR}, not {year}\")\n    if not 1 <= month <= 12:\n        raise ValueError(f\"month must be in 1..12, not {month}\")\n    dim = _days_in_month(year, month)\n    if not 1 <= day <= dim:\n        raise ValueError(f\"day {day} must be in range 1..{dim} for month {month} in year {year}\")\n    return year, month, day\n\ndef _check_time_fields(hour, minute, second, microsecond, fold):\n    hour = _index(hour)\n    minute = _index(minute)\n    second = _index(second)\n    microsecond = _index(microsecond)\n    if not 0 <= hour <= 23:\n        raise ValueError(f\"hour must be in 0..23, not {hour}\")\n    if not 0 <= minute <= 59:\n        raise ValueError(f\"minute must be in 0..59, not {minute}\")\n    if not 0 <= second <= 59:\n        raise ValueError(f\"second must be in 0..59, not {second}\")\n    if not 0 <= microsecond <= 999999:\n        raise ValueError(f\"microsecond must be in 0..999999, not {microsecond}\")\n    if fold not in (0, 1):\n        raise ValueError(f\"fold must be either 0 or 1, not {fold}\")\n    return hour, minute, second, microsecond, fold\n\ndef _check_tzinfo_arg(tz):\n    if tz is not None and not isinstance(tz, tzinfo):\n        raise TypeError(\n            \"tzinfo argument must be None or of a tzinfo subclass, \"\n            f\"not {type(tz).__name__!r}\"\n        )\n\ndef _divide_and_round(a, b):\n    \"\"\"divide a by b and round result to the nearest integer\n","sourceCodeStart":571,"sourceCodeEnd":607,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pydatetime.py#L571-L607","documentation":"Raised by _check_time_fields() when the minute argument to time()/datetime() is not in 0..59. Minutes never reach 60 even for leap-second-aware timestamps — Python datetime does not model leap seconds, so 60 is rejected here (it is also rejected for seconds).","triggerScenarios":"time(12, 60); datetime(2024, 1, 1, 12, -1); parsing strings like '12:60'; carrying errors when adding minutes without normalizing.","commonSituations":"Hand-written time parsers accepting mm=60; arithmetic that adds minutes to the field instead of using timedelta; timezone offsets applied to the minute field directly.","solutions":["Use timedelta arithmetic instead of mutating minute fields","Normalize: h, m = divmod(total_minutes, 60) before constructing","Validate 0 <= minute <= 59 in parser input paths"],"exampleFix":"// before\nt = time(11, 75)  # ValueError\n// after\nbase = datetime(y, m, d, 11, 0) + timedelta(minutes=75)\nt = base.time()","handlingStrategy":"validation","validationCode":"if not 0 <= minute <= 59:\n    raise ValueError('minute must be 0..59')","typeGuard":"def valid_minute(m) -> bool:\n    return 0 <= m <= 59","tryCatchPattern":null,"preventionTips":["Do minute arithmetic with timedelta, not by mutating the field","Normalize with divmod(total_minutes, 60) before constructing"],"tags":["datetime","valueerror","validation","time"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}