{"record":{"id":"b0270b0a48fd1da3","repo":"dotnet/efcore","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/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/eng/common/cross/install-debs.py#L16-L52","documentation":"In eng/common/cross/install-debs.py (download_file, line 20-47), each downloaded .deb file is verified against a SHA256 checksum recorded in the Debian package index. After reading the response body, hashlib.sha256 is computed (line 32) and compared to the expected checksum (line 33); on mismatch a plain Exception is raised at line 34. This protects against truncated, corrupted, or tampered downloads during rootfs construction.","triggerScenarios":"A network issue (proxy cache poisoning, interrupted connection, mirror desync), a man-in-the-middle, a stale/incorrect checksum in the Packages index, or a mirror serving a different package version than its index advertises — any case where the bytes received do not hash to the expected SHA256.","commonSituations":"Building .NET runtime rootfs on a flaky corporate network or behind a caching proxy; a Debian/Ubuntu mirror partially updated (index newer than the .deb files); running an old checkout of eng/common against a moved mirror; clock/time issues causing TLS interception artifacts.","solutions":["Retry the build (download_file already retries up to max_retries=3); transient mirror desync often resolves on retry or after a short delay.","Switch to a more reliable/synced mirror via --mirror (e.g. the official debian.org mirror).","Clear any caching proxy in front of the build host, or bypass it.","Update eng/common from the dotnet/arcade repo so package index/checksums are current.","If the checksum in the index is genuinely wrong, report/verify against the distribution's published checksums."],"exampleFix":"# before\npython3 install-debs.py --mirror http://cached-proxy/debian ...\n\n# after (use a fresh official mirror and retry)\npython3 install-debs.py --mirror http://deb.debian.org/debian ...","handlingStrategy":"retry","validationCode":"# Optionally pre-verify a URL's checksum before invoking install-debs.py,\n# though the script itself is the authority. Set a reliable mirror and clean proxies:\n# export no_proxy=\"$no_proxy,deb.debian.org\"\n# Then run with the official mirror to avoid stale cached artifacts.","typeGuard":null,"tryCatchPattern":"try:\n    asyncio.run(download_deb_files_parallel(mirror, packages, tmp_dir))\nexcept Exception as e:\n    if 'SHA256 mismatch' in str(e):\n        # retry against a fresh/official mirror, or clear the caching proxy\n        mirror = 'http://deb.debian.org/debian'\n        asyncio.run(download_deb_files_parallel(mirror, packages, tmp_dir))\n    else:\n        raise","preventionTips":["Use an official, well-synced mirror via --mirror.","Disable or bypass caching proxies that may serve stale .deb artifacts.","Keep eng/common synced from dotnet/arcade so package indexes and checksums are current.","Retry transient mirror desync; persistent mismatches indicate a real mirror or network problem."],"tags":["python","debian","download","checksum","network","rootfs"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}