dotnet/runtime · error · Exception

SHA256 mismatch for {url}: expected {checksum}, got {sha256}

Error message

SHA256 mismatch for {url}: expected {checksum}, got {sha256}

What it means

install-debs.py computes the SHA-256 of downloaded .deb bytes and compares against the checksum recorded in the Packages index. A mismatch means the bytes received are not the bytes the mirror advertised - caused by a corrupt/partial download, a mirror out of sync, a transparent proxy/cache altering content, or (in the worst case) tampering. The script aborts rather than installing untrusted bytes into the rootfs.

Source

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

from collections import deque
from functools import cmp_to_key

async def download_file(session, url, dest_path, max_retries=3, retry_delay=2, timeout=60, checksum=None):
    """Asynchronous file download with retries."""
    attempt = 0
    while attempt < max_retries:
        try:
            async with session.get(url, timeout=aiohttp.ClientTimeout(total=timeout)) as response:
                if response.status == 200:
                    with open(dest_path, "wb") as f:
                        content = await response.read()

                        # verify checksum if provided
                        if checksum:
                            sha256 = hashlib.sha256(content).hexdigest()
                            if sha256 != checksum:
                                raise Exception(f"SHA256 mismatch for {url}: expected {checksum}, got {sha256}")

                        f.write(content)
                    print(f"Downloaded {url} at {dest_path}")
                    return
                else:
                    raise Exception(f"Failed to download {url}, Status Code: {response.status}")
        except (asyncio.CancelledError, asyncio.TimeoutError, aiohttp.ClientError) as e:
            print(f"Error downloading {url}: {type(e).__name__} - {e}. Retrying...")

        attempt += 1
        await asyncio.sleep(retry_delay)

    raise Exception(f"Failed to download {url} after {max_retries} attempts.")

async def download_deb_files_parallel(mirror, packages, tmp_dir):
    """Download .deb files in parallel."""
    os.makedirs(tmp_dir, exist_ok=True)

View on GitHub (pinned to 60108ba66e)

Solutions

  1. Re-run the rootfs build; transient mirror/CDN desync usually clears within minutes.
  2. Switch to a more up-to-date or official mirror via --mirror.
  3. If behind a proxy, exclude the mirror domain from interception or use an internal mirror known to pass through bytes verbatim.
  4. Clear the temp dir and let install-debs.py re-download from scratch.

Example fix

# before
python3 install-debs.py --arch arm64 --rootfsdir rootfs --suite bookworm --mirror http://bad-mirror/debian libc6
# raises SHA256 mismatch

# after
python3 install-debs.py --arch arm64 --rootfsdir rootfs --suite bookworm --mirror http://deb.debian.org/debian libc6
Defensive patterns

Strategy: validation

Validate before calling

# Pre-validate checksums you will pass to download_file by recomputing on a trusted copy.
import hashlib
def expected_sha256(path_or_url_known_good: bytes) -> str:
    return hashlib.sha256(path_or_url_known_good).hexdigest()

# Before installing: confirm your mirror serves byte-identical content by fetching
# from a second trusted mirror and comparing SHA-256.

Try / catch

# install-debs.py already retries via download_file; wrap the top-level call:
try:
    main()
except Exception as e:
    if 'SHA256 mismatch' in str(e):
        print('Mirror served bytes that disagree with the Packages index; try a different --mirror.')
        sys.exit(2)
    raise

Prevention

When it happens

Trigger: download_file fetches a .deb whose SHA256 differs from info['SHA256'] parsed from the Packages index. Raised at install-debs.py:33-34. Triggered by network corruption, a flaky mirror, a stale CDN edge, or a man-in-the-middle.

Common situations: Building a cross-arch rootfs behind a corporate HTTP proxy that rewrites responses. A Debian mirror mid-update (partial replication). A retry that landed on a different mirror with different content. Transient disk corruption in the temp download.

Related errors


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