{"record":{"id":"d8b102b863b2ca8d","repo":"denoland/deno","slug":"checksum-mismatch-for-archive-downloaded-from","errorCode":null,"errorMessage":"checksum mismatch for {archive} (downloaded from {url})\\n  expected: {expected_lc}\\n  actual:   {actual}","messagePattern":"checksum mismatch for (.+?) \\(downloaded from (.+?)\\)\\\\n  expected: (.+?)\\\\n  actual:   (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"cli/tools/desktop.rs","lineNumber":1994,"sourceCode":"      env!(\"CARGO_PKG_VERSION\")\n    )) {\n      headers.insert(http::header::USER_AGENT, ua);\n    }\n    let response = client\n      .download_with_progress_and_retries(url.clone(), &headers, &progress)\n      .await\n      .with_context(|| format!(\"failed to download {url}\"))?;\n    let data = response\n      .into_maybe_bytes()?\n      .ok_or_else(|| deno_core::anyhow::anyhow!(\"empty response from {url}\"))?;\n\n    let actual =\n      faster_hex::hex_string(&sha2::Sha256::digest(&data)).to_lowercase();\n    let expected_lc = expected.to_lowercase();\n    if actual != expected_lc {\n      // Include the URL in the bail: an attacker who poisoned a redirect\n      // would otherwise be invisible in the failure log.\n      bail!(\n        \"checksum mismatch for {archive} (downloaded from {url})\\n  expected: {expected_lc}\\n  actual:   {actual}\"\n      );\n    }\n\n    let parent = dir.parent().ok_or_else(|| {\n      deno_core::anyhow::anyhow!(\n        \"LAUFEY cache dir has no parent: {}\",\n        dir.display()\n      )\n    })?;\n    std::fs::create_dir_all(parent)?;\n\n    // Stage extraction in a sibling tempdir so concurrent `deno desktop`\n    // builds don't see (or stomp on) a half-populated `dir` while one\n    // is mid-extract. tempfile's cleanup-on-drop covers panic /\n    // early-return paths; on the happy path we consume the TempDir via\n    // `into_path` so the rename below sees a real directory.\n    let staging = tempfile::Builder::new()","sourceCodeStart":1976,"sourceCodeEnd":2012,"githubUrl":"https://github.com/denoland/deno/blob/f7822238cab635a3a19f99f493f675fa81a7f9d8/cli/tools/desktop.rs#L1976-L2012","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\ndeno desktop main.ts   # checksum mismatch for laufey-cef-...tar.gz\n\n# after (verify what the network actually delivers, then retry)\ncurl -sL <url-from-error> | sha256sum   # compare to expected: value\nrm -rf ~/.cache/deno-desktop-laufey     # clear partial download\ndeno desktop main.ts","handlingStrategy":"retry","validationCode":"# bash: pre-verify the release asset hash matches the pin before building\ncurl -sL \"<laufey-release-url>\" -o /tmp/laufey.tar.gz\nACTUAL=\"$(sha256sum /tmp/laufey.tar.gz | cut -d' ' -f1)\"\n[[ \"$ACTUAL\" == \"<expected-sha256>\" ]] || { echo \"upstream hash drifted\" >&2; exit 1; }","typeGuard":null,"tryCatchPattern":"# Wrap the build; retry transient truncation once, escalate on repeat\nset +e; deno desktop main.ts 2>&1 | tee build.log; RC=${PIPESTATUS[0]}; set -e\nif [[ $RC -ne 0 ]] && grep -q \"checksum mismatch\" build.log; then\n  rm -rf \"$HOME/.cache/deno-desktop-laufey\"\n  deno desktop main.ts || { echo \"persistent checksum mismatch — possible tampering\" >&2; exit 1; }\nfi","preventionTips":["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."],"tags":["desktop","laufey","checksum","sha256","download","supply-chain"],"backgroundTag":"checksum-mismatch","analyzedSha":"f7822238cab635a3a19f99f493f675fa81a7f9d8","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-31T04:17:50.494Z"}