denoland/deno · critical
checksum mismatch for {archive} (downloaded from {url})\n e
Error message
checksum mismatch for {archive} (downloaded from {url})\n expected: {expected_lc}\n actual: {actual} What it means
Thrown while fetching the LAUFEY backend runtime archive: the SHA-256 of the downloaded bytes does not match the pinned expected hash for that archive. The message deliberately includes the download URL because a poisoned redirect would otherwise be invisible in the failure log. Causes range from a truncated/corrupted transfer (proxy, flaky network) to a tampered or mis-pinned release.
Source
Thrown at cli/tools/desktop.rs:1994
env!("CARGO_PKG_VERSION")
)) {
headers.insert(http::header::USER_AGENT, ua);
}
let response = client
.download_with_progress_and_retries(url.clone(), &headers, &progress)
.await
.with_context(|| format!("failed to download {url}"))?;
let data = response
.into_maybe_bytes()?
.ok_or_else(|| deno_core::anyhow::anyhow!("empty response from {url}"))?;
let actual =
faster_hex::hex_string(&sha2::Sha256::digest(&data)).to_lowercase();
let expected_lc = expected.to_lowercase();
if actual != expected_lc {
// Include the URL in the bail: an attacker who poisoned a redirect
// would otherwise be invisible in the failure log.
bail!(
"checksum mismatch for {archive} (downloaded from {url})\n expected: {expected_lc}\n actual: {actual}"
);
}
let parent = dir.parent().ok_or_else(|| {
deno_core::anyhow::anyhow!(
"LAUFEY cache dir has no parent: {}",
dir.display()
)
})?;
std::fs::create_dir_all(parent)?;
// Stage extraction in a sibling tempdir so concurrent `deno desktop`
// builds don't see (or stomp on) a half-populated `dir` while one
// is mid-extract. tempfile's cleanup-on-drop covers panic /
// early-return paths; on the happy path we consume the TempDir via
// `into_path` so the rename below sees a real directory.
let staging = tempfile::Builder::new()View on GitHub (pinned to f7822238ca)
Solutions
- Retry the build — transient truncation is the most common cause; the cached partial file is replaced on the next attempt.
- Download the URL from the error message manually and compare: `curl -L <url> | sha256sum` against the `expected:` value to distinguish network corruption from a bad pin.
- Check proxy/SSL-inspection and free disk space in the cache dir; fix and re-run.
- If the hash reproducibly mismatches the official release asset, report it to the deno/laufey maintainers — it may indicate a compromised or re-cut release.
Example fix
# before deno desktop main.ts # checksum mismatch for laufey-cef-...tar.gz # after (verify what the network actually delivers, then retry) curl -sL <url-from-error> | sha256sum # compare to expected: value rm -rf ~/.cache/deno-desktop-laufey # clear partial download deno desktop main.ts
Defensive patterns
Strategy: retry
Validate before calling
# bash: pre-verify the release asset hash matches the pin before building
curl -sL "<laufey-release-url>" -o /tmp/laufey.tar.gz
ACTUAL="$(sha256sum /tmp/laufey.tar.gz | cut -d' ' -f1)"
[[ "$ACTUAL" == "<expected-sha256>" ]] || { echo "upstream hash drifted" >&2; exit 1; } Try / catch
# Wrap the build; retry transient truncation once, escalate on repeat
set +e; deno desktop main.ts 2>&1 | tee build.log; RC=${PIPESTATUS[0]}; set -e
if [[ $RC -ne 0 ]] && grep -q "checksum mismatch" build.log; then
rm -rf "$HOME/.cache/deno-desktop-laufey"
deno desktop main.ts || { echo "persistent checksum mismatch — possible tampering" >&2; exit 1; }
fi Prevention
- Keep networks that intercept TLS (corporate proxies) from mangling large downloads.
- Ensure the cache directory is on a volume with free space.
- Treat a reproducible mismatch as a security signal and report it, never as something to skip.
When it happens
Trigger: Corporate proxy or flaky CDN returning a partial body or an HTML error page; a MITM rewriting the download; the pinned hash in this Deno version not matching the actual laufey release asset after an upstream re-release; disk-full truncating the written cache file.
Common situations: First build behind a captive/SSL-inspecting proxy; CI runner with an unstable network; laufey release tag re-uploaded with different assets; a full disk in the cache directory.
Related errors
- no pinned SHA-256 for {archive} in cli/laufey_sums.lock (reg
- Checksum verification failed. Actual: {} Expected: {}
- LAUFEY backend exited with status: {}
- refusing tar entry with traversal path: {}
- refusing tar entry that would unpack outside dest: {}
AI-assisted analysis of denoland/deno@f7822238ca (2026-08-20).
Data as JSON: /api/errors/d8b102b863b2ca8d.
Report an issue: GitHub.