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

  1. 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.
  2. 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.
  3. 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).
  4. 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

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


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 GitHub

View on GitHub (pinned to f7822238ca)