denoland/deno · error
no pinned SHA-256 for
Error message
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}') What it means
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.
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.
Example fix
# before: bumping only the version constant # LAUFEY_VERSION = "1.2.3" (lock still pins 1.2.2) deno desktop # error: no pinned SHA-256 for laufey-aarch64-apple-darwin.tar.gz ... # after: regenerate the lock in the same change # (fetch release archives, sha256sum them, update the file) $EDITOR cli/laufey_sums.lock # add laufey-aarch64-apple-darwin.tar256 entry cargo build -p deno # build-time assert re-checks lock vs LAUFEY_VERSION deno desktop
Defensive patterns
Strategy: validation
Validate before calling
# Before running the desktop build, confirm the pinned lock covers the archive
# for the exact backend/target you will request:
archive="laufey-${target}.tar.gz" # or .zip for windows targets
grep -qF "$archive" cli/laufey_sums.lock \
|| echo "WARN: lock has no entry for $archive at the pinned LAUFEY_VERSION" Try / catch
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. Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- checksum mismatch for
- could not find ' ' backend binary under (set via )
- build failed (exit code: )
- cli/laufey_sums.lock has no pinned laufey version —…
- cli/laufey_sums.lock pins Laufey v
AI-assisted analysis of denoland/deno@f7822238ca (2026-08-20).
Data as JSON: /api/errors/851b508fe0ae7ebd.
Report an issue: GitHub.
Appendix: source
Thrown at cli/tools/desktop.rs:1953
target: &str,
) -> Result<PathBuf, AnyError> {
let dir = self.backend_cache_dir(backend, target);
let marker = dir.join(".downloaded");
if marker.exists() {
return Ok(dir);
}
let archive = laufey_archive_name(backend, target);
let client = self.http_client_provider.get_or_create()?;
// Use the in-tree pinned digests rather than fetching SHA256SUMS from the
// release page. The latter is unsigned, so trusting it would let anyone
// who can write to the laufey release host swap both archive and sums
// together (TOFU). The lock file is reviewed in PRs when LAUFEY_VERSION
// bumps, so this is the trust anchor. That the lock file's pinned version
// matches LAUFEY_VERSION is asserted at build time (see cli/build.rs).
let expected = parse_sha256sum(LAUFEY_PINNED_SUMS, &archive).ok_or_else(|| {
deno_core::anyhow::anyhow!(
"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}')"
)
})?;
log::info!(
"{} laufey {} backend for {} (v{})",
colors::green("Downloading"),
backend,
target,
LAUFEY_VERSION,
);
let url = Url::parse(&laufey_release_url(&archive))?;
let progress_bar = ProgressBar::new(ProgressBarStyle::DownloadBars);
let progress = progress_bar.update(&archive);
// Send a real User-Agent — some CDNs (incl. parts of GitHubView on GitHub (pinned to f7822238ca)