dotnet/runtime · error · Exception

SHA256 mismatch for {path}: expected {packages_sha}, got {sh

Error message

SHA256 mismatch for {path}: expected {packages_sha}, got {sha256}

What it means

When --force-check-gpg is set, install-debs.py hashes the compressed Packages.gz bytes and compares against the SHA-256 recorded for that path in the cryptographically signed Release file. A mismatch means the package index itself is not what the distribution signed - mirror desync, a transparent proxy rewriting responses, or an attack. The build refuses to trust an index whose checksum does not match the signature.

Source

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

    """Fetch and decompress the Packages.gz file."""

    path = f"{component}/binary-{arch}/Packages.gz"
    url = f"{mirror}/dists/{suite}/{path}"

    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}")

            if check_sig:
                # Verify the package index against the sha256 recorded in the Release file
                release_file_content = await fetch_release_file(session, mirror, suite, keyring)
                packages_sha = parse_release_file(release_file_content, path)

                sha256 = hashlib.sha256(compressed_data).hexdigest()
                if sha256 != packages_sha:
                    raise Exception(f"SHA256 mismatch for {path}: expected {packages_sha}, got {sha256}")
                print(f"Checksum verified for {path}")

            return decompressed_data
        else:
            print(f"Skipped index: {url} (doesn't exist)")
            return None

async def fetch_release_file(session, mirror, suite, keyring):
    """Fetch Release and Release.gpg files and verify the signature."""

    release_url = f"{mirror}/dists/{suite}/Release"
    release_gpg_url = f"{mirror}/dists/{suite}/Release.gpg"

    with tempfile.NamedTemporaryFile() as release_file, tempfile.NamedTemporaryFile() as release_gpg_file:
        await download_file(session, release_url, release_file.name)
        await download_file(session, release_gpg_url, release_gpg_file.name)

        print("Verifying signature of Release with Release.gpg.")

View on GitHub (pinned to 60108ba66e)

Solutions

  1. Re-run the rootfs build; mirror desync usually self-heals.
  2. Point --mirror at a different, fully-replicated mirror (e.g. the official deb.debian.org / ports mirror).
  3. Bypass any HTTP proxy that may be caching inconsistent bodies.
  4. If you trust the environment, drop --force-check-gpg (or use --skipsigcheck in build-rootfs.sh), but prefer fixing the mirror.

Example fix

# before
python3 install-debs.py --force-check-gpg --keyring debian.kbx --suite trixie --mirror http://stale-mirror/debian ...
# SHA256 mismatch on Packages.gz

# after
python3 install-debs.py --force-check-gpg --keyring debian.kbx --suite trixie --mirror http://deb.debian.org/debian ...
Defensive patterns

Strategy: validation

Validate before calling

# Before trusting an index, fetch Release and Packages.gz independently and compare SHA-256.
import hashlib, aiohttp, asyncio
async def verify_index(mirror, suite, path):
    async with aiohttp.ClientSession() as s:
        async with s.get(f'{mirror}/dists/{suite}/Release') as r: rel = await r.text()
        async with s.get(f'{mirror}/dists/{suite}/{path}') as r: gz = await r.read()
    expected = parse_release_file(rel, path)
    actual = hashlib.sha256(gz).hexdigest()
    return expected == actual

Try / catch

try:
    main()
except Exception as e:
    if 'SHA256 mismatch' in str(e) and 'Packages' in str(e):
        print('Signed Release disagrees with served Packages.gz; switch --mirror or wait for sync.')
        sys.exit(2)
    raise

Prevention

When it happens

Trigger: fetch_and_decompress computes SHA-256 of the downloaded Packages.gz content and it differs from parse_release_file(release, path). Raised at install-debs.py:104-105. Happens on mirror replication lag, CDN edge staleness, or proxy interference, when --force-check-gpg is on.

Common situations: Mirror mid-update (Release file updated before Packages.gz replicates). HTTP proxy caching stale bodies. CDN layer serving mixed versions. Rare man-in-the-middle tampering.

Related errors


AI-assisted analysis of dotnet/runtime@60108ba66e (2026-08-10). Data as JSON: /api/errors/574eefb3ff2b3d55. Report an issue: GitHub.