dotnet/maui · error · ValueError

Invalid Debian version format: {version}

Error message

Invalid Debian version format: {version}

What it means

parse_debian_version raises ValueError when the supplied version string does not match the Debian version regex `^(?:(\d+):)?([^-]+)(?:-(.+))$` (optional epoch, non-empty upstream, optional revision). The parser is used to compare package versions when selecting debs for a cross-build rootfs; an unparseable version halts rootfs setup.

Source

Thrown at eng/common/cross/install-debs.py:99

    """Fetch and decompress the Packages.gz file."""
    try:
        async with session.get(url) as response:
            if response.status == 200:
                compressed_data = await response.read()
                decompressed_data = gzip.decompress(compressed_data).decode('utf-8')
                print(f"Downloaded index: {url}")
                return decompressed_data
            else:
                print(f"Skipped index: {url} (doesn't exist)")
                return None
    except Exception as e:
        print(f"Error fetching {url}: {e}")

def parse_debian_version(version):
    """Parse a Debian package version into epoch, upstream version, and revision."""
    match = re.match(r'^(?:(\d+):)?([^-]+)(?:-(.+))?$', version)
    if not match:
        raise ValueError(f"Invalid Debian version format: {version}")
    epoch, upstream, revision = match.groups()
    return int(epoch) if epoch else 0, upstream, revision or ""

def compare_upstream_version(v1, v2):
    """Compare upstream or revision parts using Debian rules."""
    def tokenize(version):
        tokens = re.split(r'([0-9]+|[A-Za-z]+)', version)
        return [int(x) if x.isdigit() else x for x in tokens if x]

    tokens1 = tokenize(v1)
    tokens2 = tokenize(v2)

    for token1, token2 in zip(tokens1, tokens2):
        if type(token1) == type(token2):
            if token1 != token2:
                return (token1 > token2) - (token1 < token2)
        else:
            return -1 if isinstance(token1, str) else 1

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Inspect the version string passed in; ensure it matches epoch:upstream-revision form (e.g. `1:1.2.3-4`).
  2. If the index is malformed, switch --mirror to the official Debian/Ubuntu mirror or clear the cached index.
  3. Wrap the call and skip/log packages whose versions fail to parse rather than aborting the whole rootfs.
  4. Pin --suite to a stable release whose package versions are well-formed.

Example fix

# before
epoch, upstream, rev = parse_debian_version(bad_version)

# after
import re
if not re.match(r'^(?:(\d+):)?([^-]+)(?:-(.+))?$', bad_version):
    print(f"Skipping malformed version: {bad_version}"); continue
epoch, upstream, rev = parse_debian_version(bad_version)
Defensive patterns

Strategy: validation

Validate before calling

import re
if not re.match(r'^(?:(\d+):)?([^-]+)(?:-(.+))?$', version):
    raise ValueError(f"Invalid Debian version format: {version}")

Type guard

import re
def is_valid_debian_version(v): return bool(re.match(r'^(?:(\d+):)?([^-]+)(?:-(.+))?$', v))

Try / catch

try:
    epoch, up, rev = parse_debian_version(v)
except ValueError as e:
    print(f"skip {v}: {e}"); continue

Prevention

When it happens

Trigger: Passing a malformed version to parse_debian_version: empty string, a string starting with '-', a revision-only fragment, or a version containing characters the regex rejects in the upstream segment. Triggered when the Packages index contains an unexpected version field.

Common situations: A mirror returns a Packages index with non-standard versions, a hand-edited version list, or a proxy/cache that mangles the version string.

Related errors


AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13). Data as JSON: /api/errors/d01484d0da7ff623. Report an issue: GitHub.