{"record":{"id":"851b508fe0ae7ebd","repo":"denoland/deno","slug":"no-pinned-sha-256-for-archive-in-cli-laufey-sums","errorCode":null,"errorMessage":"no pinned SHA-256 for {archive} in cli/laufey_sums.lock (regenerate when bumping LAUFEY_VERSION to v{LAUFEY_VERSION}; laufey v{LAUFEY_VERSION} release may not include backend '{backend}' for target '{target}')","messagePattern":"no pinned SHA-256 for (.+?) in cli/laufey_sums\\.lock \\(regenerate when bumping LAUFEY_VERSION to v(.+?); laufey v(.+?) release may not include backend '(.+?)' for target '(.+?)'\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/tools/desktop.rs","lineNumber":1953,"sourceCode":"    target: &str,\n  ) -> Result<PathBuf, AnyError> {\n    let dir = self.backend_cache_dir(backend, target);\n    let marker = dir.join(\".downloaded\");\n    if marker.exists() {\n      return Ok(dir);\n    }\n\n    let archive = laufey_archive_name(backend, target);\n    let client = self.http_client_provider.get_or_create()?;\n\n    // Use the in-tree pinned digests rather than fetching SHA256SUMS from the\n    // release page. The latter is unsigned, so trusting it would let anyone\n    // who can write to the laufey release host swap both archive and sums\n    // together (TOFU). The lock file is reviewed in PRs when LAUFEY_VERSION\n    // bumps, so this is the trust anchor. That the lock file's pinned version\n    // matches LAUFEY_VERSION is asserted at build time (see cli/build.rs).\n    let expected = parse_sha256sum(LAUFEY_PINNED_SUMS, &archive).ok_or_else(|| {\n      deno_core::anyhow::anyhow!(\n        \"no pinned SHA-256 for {archive} in cli/laufey_sums.lock \\\n         (regenerate when bumping LAUFEY_VERSION to v{LAUFEY_VERSION}; \\\n         laufey v{LAUFEY_VERSION} release may not include backend '{backend}' for target '{target}')\"\n      )\n    })?;\n\n    log::info!(\n      \"{} laufey {} backend for {} (v{})\",\n      colors::green(\"Downloading\"),\n      backend,\n      target,\n      LAUFEY_VERSION,\n    );\n\n    let url = Url::parse(&laufey_release_url(&archive))?;\n    let progress_bar = ProgressBar::new(ProgressBarStyle::DownloadBars);\n    let progress = progress_bar.update(&archive);\n    // Send a real User-Agent — some CDNs (incl. parts of GitHub","sourceCodeStart":1935,"sourceCodeEnd":1971,"githubUrl":"https://github.com/denoland/deno/blob/f7822238cab635a3a19f99f493f675fa81a7f9d8/cli/tools/desktop.rs#L1935-L1971","documentation":"The deno desktop (laufey backend) installer pins every downloadable archive's SHA-256 in the in-tree cli/laufey_sums.lock file instead of trusting the unsigned SHA256SUMS on the release page. This error means the archive name computed for the requested backend/target (e.g. laufey-aarch64-apple-darwin.tar.gz) has no matching entry in the pinned sums for the current LAUFEY_VERSION. It is a trust-anchor failure: the build refuses to download anything it cannot verify.","triggerScenarios":"Running `deno desktop` (download path) when parse_sha256sum(LAUFEY_PINNED_SUMS, &archive) returns None: the backend/target combination has no line in cli/laufey_sums.lock for the pinned version. Typically after LAUFEY_VERSION was bumped but laufey_sums.lock was not regenerated, or when the requested backend simply does not ship for that target in the laufey release.","commonSituations":"A developer bumps LAUFEY_VERSION in cli/build.rs or desktop.rs and forgets to regenerate cli/laufey_sums.lock in the same PR; a user passes an exotic backend/target pair (e.g. a backend that only ships for macOS requested for linux); the laufey release for the new version renamed its archive naming scheme.","solutions":["If you maintain this checkout: regenerate cli/laufey_sums.lock by downloading the v{LAUFEY_VERSION} release SHA256SUMS out-of-band, verifying them, and adding the archive digest for every backend/target pair, then rebuild.","If you are a consumer: pick a backend/target combination that the pinned laufey release actually ships (check the release assets for v{LAUFEY_VERSION}) and re-run.","Update to a deno version whose LAUFEY_VERSION and laufey_sums.lock are in sync (the match is asserted at build time in cli/build.rs, so released builds should never hit this).","For local development of laufey itself, set LAUFEY_DEV_DIR to a built checkout so the download path (and its lock requirement) is skipped entirely."],"exampleFix":"# before: bumping only the version constant\n# LAUFEY_VERSION = \"1.2.3\"  (lock still pins 1.2.2)\ndeno desktop\n# error: no pinned SHA-256 for laufey-aarch64-apple-darwin.tar.gz ...\n\n# after: regenerate the lock in the same change\n# (fetch release archives, sha256sum them, update the file)\n$EDITOR cli/laufey_sums.lock   # add laufey-aarch64-apple-darwin.tar256 entry\ncargo build -p deno           # build-time assert re-checks lock vs LAUFEY_VERSION\ndeno desktop","handlingStrategy":"validation","validationCode":"# Before running the desktop build, confirm the pinned lock covers the archive\n# for the exact backend/target you will request:\narchive=\"laufey-${target}.tar.gz\"   # or .zip for windows targets\ngrep -qF \"$archive\" cli/laufey_sums.lock \\\n  || echo \"WARN: lock has no entry for $archive at the pinned LAUFEY_VERSION\"","typeGuard":null,"tryCatchPattern":"Match on the error text 'no pinned SHA-256' and surface a targeted message ('backend not shipped for target / lock out of sync') instead of the generic download failure; never retry — the lock is compile-time data and will not change between attempts.","preventionTips":["Treat LAUFEY_VERSION and cli/laufey_sums.lock as one atomic change: regenerate the lock in the same commit as the version bump.","Add a CI matrix step that checks the lock contains an entry for every backend/target pair the CLI can request.","Rely on the build-time assertion in cli/build.rs to fail the build (not runtime) when lock and version drift."],"tags":["checksum","supply-chain","build","laufey","desktop"],"backgroundTag":"checksum-pin-missing","analyzedSha":"f7822238cab635a3a19f99f493f675fa81a7f9d8","analyzedAt":"2026-08-20T13:07:44.778Z","contentChangedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}