{"record":{"id":"8b2fea2ff9f79cc5","repo":"dotnet/aspnetcore","slug":"sha256-mismatch-for-url-expected-checksum-go","errorCode":null,"errorMessage":"SHA256 mismatch for {url}: expected {checksum}, got {sha256}","messagePattern":"SHA256 mismatch for (.+?): expected (.+?), got (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"eng/common/cross/install-debs.py","lineNumber":34,"sourceCode":"\nfrom collections import deque\nfrom functools import cmp_to_key\n\nasync def download_file(session, url, dest_path, max_retries=3, retry_delay=2, timeout=60, checksum=None):\n    \"\"\"Asynchronous file download with retries.\"\"\"\n    attempt = 0\n    while attempt < max_retries:\n        try:\n            async with session.get(url, timeout=aiohttp.ClientTimeout(total=timeout)) as response:\n                if response.status == 200:\n                    with open(dest_path, \"wb\") as f:\n                        content = await response.read()\n\n                        # verify checksum if provided\n                        if checksum:\n                            sha256 = hashlib.sha256(content).hexdigest()\n                            if sha256 != checksum:\n                                raise Exception(f\"SHA256 mismatch for {url}: expected {checksum}, got {sha256}\")\n\n                        f.write(content)\n                    print(f\"Downloaded {url} at {dest_path}\")\n                    return\n                else:\n                    raise Exception(f\"Failed to download {url}, Status Code: {response.status}\")\n        except (asyncio.CancelledError, asyncio.TimeoutError, aiohttp.ClientError) as e:\n            print(f\"Error downloading {url}: {type(e).__name__} - {e}. Retrying...\")\n\n        attempt += 1\n        await asyncio.sleep(retry_delay)\n\n    raise Exception(f\"Failed to download {url} after {max_retries} attempts.\")\n\nasync def download_deb_files_parallel(mirror, packages, tmp_dir):\n    \"\"\"Download .deb files in parallel.\"\"\"\n    os.makedirs(tmp_dir, exist_ok=True)\n","sourceCodeStart":16,"sourceCodeEnd":52,"githubUrl":"https://github.com/dotnet/aspnetcore/blob/3600ca084e9c8b5f4174fc5e747f4c52d2100806/eng/common/cross/install-debs.py#L16-L52","documentation":"Raised by install-debs.py download_file when the downloaded .deb file's SHA256 does not match the checksum recorded in the Packages index. It is a tamper/corruption guard: the bytes received from the mirror are not the bytes the package index attests to.","triggerScenarios":"download_deb_files_parallel passes info.get(\"SHA256\") from the parsed Packages index to download_file's checksum argument; the function hashes the response body and raises this Exception when hashlib.sha256(content).hexdigest() != checksum.","commonSituations":"Mirror partially updated (Packages index refreshed but .deb not yet synced, or vice versa); transparent HTTP proxy/corporate cache serving stale bytes; interrupted write where the connection was reset mid-stream but aiohttp returned a truncated body; a genuine MITM; package index for a different suite/arch than the .deb being fetched.","solutions":["Retry against a different --mirror (e.g. switch from a local mirror to http://deb.debian.org/debian or http://archive.ubuntu.com/ubuntu) to rule out mirror drift.","Disable any HTTP proxy (unset http_proxy/https_proxy) or bust the cache, then re-run.","Confirm the --suite and --arch match the index you intend (mismatch yields a checksum from the wrong Packages.gz).","If the mismatch is persistent and reproducible, file a mirror bug; do not weaken the check by removing the checksum argument."],"exampleFix":"# before\npython3 install-debs.py --mirror http://local-cache.example/debian --suite trixie --arch amd64 --rootfsdir rootfs libc6\n\n# after (switch mirror, drop proxy)\nunset http_proxy https_proxy\npython3 install-debs.py --mirror http://deb.debian.org/debian --suite trixie --arch amd64 --rootfsdir rootfs libc6","handlingStrategy":"retry","validationCode":"# Before invoking install-debs.py, sanity-check the mirror's index freshness:\ncurl -fsS --head \"$MIRROR/dists/$SUITE/Release\" | head -1\ncurl -fsS \"$MIRROR/dists/$SUCE/Release\" | grep -A2 '^SHA256:'\n# Compare a sample .deb path's SHA256 between the index and the file; mismatch before the run => use another mirror.","typeGuard":null,"tryCatchPattern":"try:\n    asyncio.run(download_deb_files_parallel(mirror, packages, tmp))\nexcept Exception as e:\n    if 'SHA256 mismatch' in str(e):\n        print('Mirror checksum drift; switch mirror and retry.')\n        raise","preventionTips":["Use a canonical mirror (deb.debian.org, archive.ubuntu.com) for reproducibility.","Disable HTTP proxies that may serve stale cached bytes.","Pin --suite to a stable release rather than a rolling alias to avoid mid-publish drift."],"tags":["python","network","checksum","debian","security","cross-build"],"backgroundTag":null,"analyzedSha":"3600ca084e9c8b5f4174fc5e747f4c52d2100806","analyzedAt":"2026-08-11T16:32:30.678Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}