dotnet/efcore · critical · Exception
SHA256 mismatch for {path}: expected {packages_sha}, got {sh
Error message
SHA256 mismatch for {path}: expected {packages_sha}, got {sha256} What it means
Raised by fetch_and_decompress when --force-check-gpg is on: the SHA256 of the just-downloaded Packages.gz does not equal the SHA256 recorded for that path in the (signature-verified) Release file. A mismatch means the bytes served for the index are not the bytes the repository signed - either mirror/CDN inconsistency during a push, a truncated/corrupt download, or an active tampering attempt.
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 dbf9771522)
Solutions
- Retry once or twice - a transient mirror/CDN inconsistency usually resolves within minutes.
- Switch to a different mirror to rule out a single bad edge cache.
- Confirm the system clock is correct; verify the Release/Release.gpg URLs by hand.
- Only as a last resort for a known-good private mirror, drop --force-check-gpg (or pass --skipsigcheck to build-rootfs.sh) - never do this to silence a mismatch on a public mirror you do not control.
Defensive patterns
Strategy: try-catch
Validate before calling
# When --force-check-gpg is on, you cannot pre-verify without re-implementing the
# fetch; instead validate inputs: mirror is https, clock is synced, suite exists.
from datetime import datetime, timezone
import urllib.parse, ntplib # 'pip install ntplib'
def preflight_for_checksum(mirror):
if urllib.parse.urlparse(mirror).scheme != "https":
raise RuntimeError("Use an https mirror when verifying checksums to avoid MITM")
off = abs(ntplib.NTPClient().request('pool.ntp.org', version=3).tx_time - datetime.now(timezone.utc).timestamp())
if off > 300:
raise RuntimeError(f"System clock off by {off:.0f}s; fix NTP before checksum verification") Try / catch
# A checksum mismatch is a security signal - never swallow it; surface and abort
try:
await download_package_index_parallel(mirror, arch, suites, check_sig=True, keyring=keyring)
except Exception as e:
if "SHA256 mismatch" in str(e):
# try ONE alternate mirror; if it also mismatches, treat as a real integrity incident
raise SystemExit(f"Integrity failure (do NOT ignore): {e}")
raise Prevention
- Prefer https mirrors to reduce MITM exposure on the index payload.
- Keep NTP running so signature/checksum validity windows are judged correctly.
- Treat any checksum mismatch as a security incident, not a transient bug.
When it happens
Trigger: fetch_and_decompress(..., check_sig=True) computes hashlib.sha256(compressed_data) and it differs from parse_release_file(release_file_content, path). Happens mid-mirror-update when Release and Packages.gz are briefly out of sync, when a CDN serves a stale/corrupt cached copy, or when a man-in-the-middle alters the payload.
Common situations: Hitting a mirror while it is mid-publish (Release updated before Packages.gz); CDN edge cache inconsistency; local transparent proxy rewriting/caching bodies; genuine MITM. Rare but security-meaningful.
Related errors
- Signature verification failed: {result.stderr.decode('utf-8'
- SHA256 mismatch for {url}: expected {checksum}, got {sha256}
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/d109f8cfda562305.
Report an issue: GitHub.