{"record":{"id":"96daee72bdb08a03","repo":"astral-sh/ruff","slug":"invalid-micro-version-micro","errorCode":null,"errorMessage":"invalid micro version: {micro}","messagePattern":"invalid micro version: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ruff_linter/src/rules/pyupgrade/rules/outdated_version_block.rs","lineNumber":238,"sourceCode":"\n    let (py_major, py_minor) = py_version.as_tuple();\n\n    match if_major.cmp(&py_major) {\n        Ordering::Less => Ok(true),\n        Ordering::Greater => Ok(false),\n        Ordering::Equal => {\n            let Some(if_minor) = check_version_iter.next() else {\n                return Ok(true);\n            };\n            let Some(if_minor) = if_minor.as_u8() else {\n                return Err(anyhow::anyhow!(\"invalid minor version: {if_minor}\"));\n            };\n\n            let if_micro = match check_version_iter.next() {\n                None => None,\n                Some(micro) => match micro.as_u8() {\n                    Some(micro) => Some(micro),\n                    None => anyhow::bail!(\"invalid micro version: {micro}\"),\n                },\n            };\n\n            Ok(if or_equal {\n                // Ex) `sys.version_info <= 3.8`. If Python 3.8 is the minimum supported version,\n                // the condition won't always evaluate to `false`, so we want to return `false`.\n                if_minor < py_minor\n            } else {\n                if let Some(if_micro) = if_micro {\n                    // Ex) `sys.version_info < 3.8.3`\n                    if_minor < py_minor || if_minor == py_minor && if_micro == 0\n                } else {\n                    // Ex) `sys.version_info < 3.8`. If Python 3.8 is the minimum supported version,\n                    // the condition _will_ always evaluate to `false`, so we want to return `true`.\n                    if_minor <= py_minor\n                }\n            })\n        }","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/astral-sh/ruff/blob/15f3fe6b15a5f00172f34b0f542f8ea277f5a586/crates/ruff_linter/src/rules/pyupgrade/rules/outdated_version_block.rs#L220-L256","documentation":"The UP036 (outdated sys.version_info block) rule compares a `sys.version_info` tuple against the target Python version. When parsing the comparison, the third (micro) element must be an integer literal; a non-integer literal (or unresolvable value) makes the comparison undecidable, so the rule bails.","triggerScenarios":"`version_always_less_than` iterated the version tuple and found a micro component whose `as_u8()` returned None — e.g. `sys.version_info < (3, 8, 'x')`, a computed value like `(3, 8, micro)`, or a float micro — instead of an integer literal.","commonSituations":"Dynamically computed version tuples, non-literal or malformed version comparisons in vendored/legacy compatibility shims, or code migrated from other tooling.","solutions":["Write the version comparison with plain integer literals: `sys.version_info < (3, 8)` or `(3, 8, 0)`","Remove the computed/dynamic micro component so UP036 can evaluate the condition","Rewrite the check using `sys.version_info >= (3, 8)` form with `if`/`else` blocks the rule can update"],"exampleFix":"# before\nif sys.version_info < (3, 8, get_micro()):\n    legacy()\n# after\nif sys.version_info < (3, 8):\n    legacy()","handlingStrategy":"validation","validationCode":"# Ensure version tuples use plain integer literals:\nif sys.version_info < (3, 8):        # OK\n    ...\nif sys.version_info < (3, 8, f()):   # breaks UP036 analysis\n    ...","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use integer literals in sys.version_info comparisons","Omit the micro component when not needed","Prefer (major, minor) tuples over (major, minor, micro) in version checks"],"tags":["ruff","pyupgrade","up036","version-check"],"backgroundTag":"autofix-failed-to-apply","analyzedSha":"15f3fe6b15a5f00172f34b0f542f8ea277f5a586","analyzedAt":"2026-09-05T10:32:37.492Z","contentChangedAt":"2026-09-05T10:32:37.492Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}