{"record":{"id":"9689c5262af1b688","repo":"dotnet/yarp","slug":"invalid-debian-version-format-version","errorCode":null,"errorMessage":"Invalid Debian version format: {version}","messagePattern":"Invalid Debian version format: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"eng/common/cross/install-debs.py","lineNumber":160,"sourceCode":"def parse_release_file(content, path):\n    \"\"\"Parses the Release file and returns sha256 checksum of the specified path.\"\"\"\n\n    # data looks like this:\n    # <checksum>  <size>  <path>\n    matches = re.findall(r'^ (\\S*) +(\\S*) +(\\S*)$', content, re.MULTILINE)\n\n    for entry in matches:\n        # the file has both md5 and sha256 checksums, we want sha256 which has a length of 64\n        if entry[2] == path and len(entry[0]) == 64:\n            return entry[0]\n\n    raise Exception(f\"Could not find checksum for {path} in Release file.\")\n\ndef parse_debian_version(version):\n    \"\"\"Parse a Debian package version into epoch, upstream version, and revision.\"\"\"\n    match = re.match(r'^(?:(\\d+):)?([^-]+)(?:-(.+))?$', version)\n    if not match:\n        raise ValueError(f\"Invalid Debian version format: {version}\")\n    epoch, upstream, revision = match.groups()\n    return int(epoch) if epoch else 0, upstream, revision or \"\"\n\ndef compare_upstream_version(v1, v2):\n    \"\"\"Compare upstream or revision parts using Debian rules.\"\"\"\n    def tokenize(version):\n        tokens = re.split(r'([0-9]+|[A-Za-z]+)', version)\n        return [int(x) if x.isdigit() else x for x in tokens if x]\n\n    tokens1 = tokenize(v1)\n    tokens2 = tokenize(v2)\n\n    for token1, token2 in zip(tokens1, tokens2):\n        if type(token1) == type(token2):\n            if token1 != token2:\n                return (token1 > token2) - (token1 < token2)\n        else:\n            return -1 if isinstance(token1, str) else 1","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/dotnet/yarp/blob/bd11867bee7df522e7fd3effb08a9c85fd616908/eng/common/cross/install-debs.py#L142-L178","documentation":"This ValueError is raised in parse_debian_version when a version string does not match the regex '^(?:(\\d+):)?([^-]+)(?:-(.+))$'. The regex decomposes a Debian version into an optional numeric epoch (followed by colon), an upstream version (no hyphens), and an optional revision (after the last hyphen). The regex fails on empty strings, strings starting with a hyphen, or strings where nothing precedes the first hyphen. Debian policy guarantees well-formed versions have at least one non-hyphen character before any revision separator, so this error indicates genuinely malformed version data in the Packages index.","triggerScenarios":"parse_debian_version (lines 156-160) is called from compare_debian_versions (lines 184-185), which is called from parse_package_index (line 238) to compare versions when selecting the highest version of a package. The ValueError fires if any package's Version field in the Packages index is empty, starts with '-', or is otherwise malformed. It can also fire if a Version field was parsed incorrectly due to the regex in parse_package_index capturing unexpected whitespace or multi-line values.","commonSituations":"A package entry in the Packages index has a missing or empty Version field (malformed index or download corruption); a version string from a non-Debian source (e.g. a PPA or third-party repo) uses a format the regex rejects; the Packages.gz decompression produced garbled output (truncation, encoding mismatch); a continuation line in the Packages index was misinterpreted, merging fields and corrupting the Version value; an epoch value contains non-digits.","solutions":["Print the offending version string (add logging before the regex match) to see exactly what failed.","Inspect the Packages index around the package whose version caused the failure -- look for field corruption or misalignment.","Re-download the package index to rule out truncation or decompression corruption.","If the version comes from a third-party repository, normalise or skip non-Debian-format versions before passing to parse_debian_version.","Broaden the regex if you need to handle non-standard versions: split on the last hyphen instead of using [^-]+.","Validate version strings with a pre-check (try matching the regex) and log a warning + skip rather than crashing the entire build."],"exampleFix":"# before -- crashes on any malformed version\nmatch = re.match(r'^(?:(\\d+):)?([^-]+)(?:-(.+))?$', version)\nif not match:\n    raise ValueError(f\"Invalid Debian version format: {version}\")\n\n# after -- split on last hyphen for robustness, warn on unexpected formats\nif '-' in version:\n    upstream, revision = version.rsplit('-', 1)\n    if ':' in upstream:\n        epoch_str, upstream = upstream.split(':', 1)\n        epoch = int(epoch_str) if epoch_str.isdigit() else 0\n    else:\n        epoch = 0\nelse:\n    epoch, upstream, revision = 0, version, \"\"\nif not upstream:\n    raise ValueError(f\"Invalid Debian version format: {version}\")","handlingStrategy":"validation","validationCode":"# Pre-validate version strings before parsing.\nimport re\n_DEBIAN_VERSION_RE = re.compile(r'^(?:(\\d+):)?([^-]+)(?:-(.+))?$')\ndef is_valid_debian_version(version):\n    return bool(version) and bool(_DEBIAN_VERSION_RE.match(version))","typeGuard":"# Validate and return None for invalid versions instead of raising\ndef safe_parse_version(version):\n    if not version or not isinstance(version, str):\n        return None\n    match = re.match(r'^(?:(\\d+):)?([^-]+)(?:-(.+))?$', version)\n    if not match:\n        return None\n    epoch, upstream, revision = match.groups()\n    return (int(epoch) if epoch else 0, upstream, revision or \"\")","tryCatchPattern":"# Wrap version comparison in try-except and skip bad entries\ntry:\n    if compare_debian_versions(version, existing_version) > 0:\n        packages[package_name] = {...}\nexcept ValueError as e:\n    print(f\"WARNING: {e}. Skipping package '{package_name}'.\")\n    continue","preventionTips":["Validate version strings with a regex pre-check before passing to parse_debian_version.","Log and skip malformed versions rather than crashing the entire build.","Sanitise version data from third-party or non-standard repositories before parsing.","Test the version parser against known-good Debian versions to ensure the regex is correct.","If handling non-Debian formats, split on the last hyphen (rsplit) instead of using [^-]+ for robustness."],"tags":["python","debian","version","regex","apt","package-index"],"backgroundTag":null,"analyzedSha":"bd11867bee7df522e7fd3effb08a9c85fd616908","analyzedAt":"2026-08-13T21:29:49.359Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}