dbt-labs/dbt-core · critical · RuntimeError
sha256 mismatch for {filename}: expected {entry['sha256']},
Error message
sha256 mismatch for {filename}: expected {entry['sha256']}, got {digest} What it means
After downloading the prebuilt wheel, `build_wheel` computes its sha256 and compares it to the digest embedded in the sdist's `assets.json`. A mismatch means the bytes fetched are not the bytes the release was packed with — so instead of installing a corrupted or tampered wheel, the backend aborts with RuntimeError.
Source
Thrown at crates/dbt-ci/templates/sdist_build_backend.py:104
with urllib.request.urlopen(req, timeout=_TIMEOUT) as resp:
return resp.read()
except (urllib.error.URLError, TimeoutError, OSError) as exc:
last = exc
if attempt < _RETRIES:
time.sleep(2 ** (attempt - 1))
raise RuntimeError(f"failed to download {url}: {last}")
def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
_emit_notice()
entry = _select_wheel()
filename = entry["filename"]
url = "{base}/{file}".format(base=_MANIFEST["base_url"].rstrip("/"), file=filename)
data = _fetch(url)
digest = hashlib.sha256(data).hexdigest()
if digest != entry["sha256"]:
raise RuntimeError(
f"sha256 mismatch for {filename}: expected {entry['sha256']}, got {digest}"
)
out = Path(wheel_directory) / filename
out.write_bytes(data)
return filename
def get_requires_for_build_wheel(config_settings=None):
return []
def build_sdist(sdist_directory, config_settings=None):
# The sdist is produced by `dbt-ci pypi pack --sdist`, not by this backend.
raise RuntimeError(
"this backend does not build sdists; use `dbt-ci pypi pack --sdist`"
)
View on GitHub (pinned to 0267ce9170)
Solutions
- Retry the install — a one-off corrupted transfer usually succeeds on a fresh download
- Clear proxy/CDN caches or bypass the proxy and download again
- Verify the published asset's actual sha256 against the manifest; if the asset was re-uploaded, republish the sdist with a regenerated assets.json (`dbt-ci pypi pack`)
- If intentional tampering is suspected, investigate before trusting any mirror
- Pin to a release where asset and manifest digests agree
Example fix
# before: repackaged wheel without regenerating manifest gh release upload mypkg-1.2.3-py3-none-mytag.whl # overwrites asset # after dbt-ci pypi pack --sdist # regenerates assets.json digests for republished assets
Defensive patterns
Strategy: validation
Validate before calling
import hashlib, json, urllib.request
manifest = json.loads(open('assets.json').read())
entry = next(iter(manifest['wheels'].values()))
data = urllib.request.urlopen(f"{manifest['base_url'].rstrip('/')}/{entry['filename']}").read()
assert hashlib.sha256(data).hexdigest() == entry['sha256'], 'asset/manifest digest mismatch — republish' Type guard
def digest_matches(data: bytes, expected: str) -> bool:
import hashlib
return hashlib.sha256(data).hexdigest() == expected Try / catch
try:
build_wheel(wheel_dir)
except RuntimeError as e:
if 'sha256 mismatch' in str(e):
print('asset corrupted or republished; do NOT install; verify release integrity')
raise SystemExit(1)
raise Prevention
- Never re-upload release assets with changed content; republish a new version with regenerated assets.json
- Verify published asset digests as part of release CI
- Avoid intercepting proxies that can corrupt large binary downloads
- Treat any mismatch as a supply-chain red flag and investigate before retrying blindly
When it happens
Trigger: `build_wheel` successfully downloads `{base_url}/{filename}` via `_fetch`, but `hashlib.sha256(data).hexdigest()` differs from `entry['sha256']` in assets.json — i.e. the downloaded artifact does not match the recorded digest.
Common situations: A corrupted or truncated download behind a misbehaving proxy; the release asset was overwritten/re-uploaded with different content (version repack) while the sdist still carries the old digest; a CDN serving a stale or wrong object; man-in-the-middle tampering.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07).
Data as JSON: /api/errors/24d597fcfe0c38cf.
Report an issue: GitHub.