{"record":{"id":"be98a9c29c89431a","repo":"pypa/pip","slug":"release-must-be-a-non-empty-tuple-of-non-negative","errorCode":null,"errorMessage":"release must be a non-empty tuple of non-negative integers, got {release}","messagePattern":"release must be a non-empty tuple of non-negative integers, got (.+?)","errorType":"validation","errorClass":"InvalidVersion","httpStatus":null,"severity":"error","filePath":"src/pip/_vendor/packaging/version.py","lineNumber":282,"sourceCode":"\ndef _validate_epoch(value: object, /) -> int:\n    epoch = value or 0\n    if isinstance(epoch, int) and epoch >= 0:\n        return epoch\n    msg = f\"epoch must be non-negative integer, got {epoch}\"\n    raise InvalidVersion(msg)\n\n\ndef _validate_release(value: object, /) -> tuple[int, ...]:\n    release = (0,) if value is None else value\n    if (\n        isinstance(release, tuple)\n        and len(release) > 0\n        and all(isinstance(i, int) and i >= 0 for i in release)\n    ):\n        return release\n    msg = f\"release must be a non-empty tuple of non-negative integers, got {release}\"\n    raise InvalidVersion(msg)\n\n\ndef _validate_pre(value: object, /) -> tuple[Literal[\"a\", \"b\", \"rc\"], int] | None:\n    if value is None:\n        return value\n    if isinstance(value, tuple) and len(value) == 2:\n        letter, number = value\n        # The letter must be a string before it can be normalized.\n        if (\n            isinstance(letter, str)\n            and (normalized := normalize_pre(letter)) in {\"a\", \"b\", \"rc\"}\n            and isinstance(number, int)\n            and number >= 0\n        ):\n            # type checkers can't infer the Literal type here on letter\n            return (normalized, number)  # type: ignore[return-value]\n    msg = f\"pre must be a tuple of ('a'|'b'|'rc', non-negative int), got {value}\"\n    raise InvalidVersion(msg)","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/pypa/pip/blob/f399c3718970b1b0e2478dac5296eb62679a9b86/src/pip/_vendor/packaging/version.py#L264-L300","documentation":"Raised by _validate_release() (version.py:273-282) when the release value passed to Version.from_parts() or Version.__replace__() is not a non-empty tuple of non-negative integers. None defaults to (0,), but any other value must be a tuple of ints where each element >= 0 and len > 0. Lists, strings, empty tuples, or tuples with negative/float/string elements all trigger this.","triggerScenarios":"Calling Version.from_parts(release=[1, 0]) (list not tuple), Version.from_parts(release=()) (empty), Version.from_parts(release=(1, -1)) (negative), or Version.from_parts(release='1.0') (string).","commonSituations":"Passing a list instead of a tuple, an empty release, or release components read as strings from JSON/config that were not converted.","solutions":["Pass release as a non-empty tuple of non-negative ints, e.g. (1, 2, 3).","Convert lists with tuple(lst) and ensure all elements are int >= 0 before calling.","Provide at least one release component; use (0,) for a zero version."],"exampleFix":"// before\nVersion.from_parts(release=[1, 0])\n// after\nVersion.from_parts(release=(1, 0))","handlingStrategy":"type-guard","validationCode":"from packaging.version import Version, InvalidVersion\n\ndef safe_from_parts(*, release, **kwargs):\n    if not isinstance(release, tuple) or len(release) == 0:\n        raise TypeError(\"release must be a non-empty tuple\")\n    if not all(isinstance(i, int) and i >= 0 for i in release):\n        raise TypeError(\"release must contain only non-negative ints\")\n    return Version.from_parts(release=release, **kwargs)","typeGuard":"def is_valid_release(value) -> bool:\n    return (\n        isinstance(value, tuple)\n        and len(value) > 0\n        and all(isinstance(i, int) and i >= 0 for i in value)\n    )","tryCatchPattern":"from packaging.version import InvalidVersion\n\ntry:\n    v = Version.from_parts(release=release)\nexcept InvalidVersion as e:\n    if \"release\" in str(e):\n        logger.error(\"Invalid release value: %s\", release)\n    raise","preventionTips":["Pass release as a tuple of non-negative ints, never a list or string","Convert lists with tuple() before calling","Ensure at least one component is provided; use (0,) for zero"],"tags":["version","release","packaging","pep440"],"backgroundTag":null,"analyzedSha":"f399c3718970b1b0e2478dac5296eb62679a9b86","analyzedAt":"2026-08-08T23:01:42.227Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}