jdx/mise · error

packslip: @ : manifest digest differs from signed list

Error message

packslip:{project}@{}: manifest digest differs from signed list

What it means

mise downloaded a packslip manifest and computed its sha256, but it does not match a digest declared by the signed vendor list (or the stamp). The manifest on the wire is not the one the vendor signed, so mise rejects it.

Solutions

  1. Wait for / ask the vendor to republish the signed release list so its digest matches the current manifest
  2. Clear any mirror/CDN cache so the digest-matching manifest is served
  3. If you control the manifest, re-sign the release list to include the manifest's current sha256

Example fix

null
Defensive patterns

Strategy: retry

Validate before calling

sha256sum <manifest>  # compare with the digest pinned in the signed release list before distributing

Type guard

null

Try / catch

// retry from a different source; a persistent mismatch means upstream desync
for attempt in 0..2 {
    match install() {
        Err(e) if e.to_string().contains("digest differs") && attempt == 0 => { clear_mirror_cache(); continue; }
        r => { r?; break; }
    }
}

Prevention

When it happens

Trigger: verified_release hashing the fetched text (Sha256::digest) and comparing against each entry of vendor_digest and stamp.digest; any single mismatch bails — vendor republished content without updating the signed list, or the file was tampered with/corrupted in transit.

Common situations: A mirror serving a modified manifest; the vendor re-signed a new manifest but the release list still pins the old digest (or vice versa); CDN/cache serving a stale manifest; MITM or supply-chain attack attempt.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/c2cd4d3b4d27ca1a. Report an issue: GitHub.

Appendix: source

Thrown at src/backend/packslip.rs:922

                    stamp.entry.packslip.clone(),
                    self.vendor_entry(project, tv, pin, opts)
                        .await?
                        .and_then(|vendor| vendor.digest),
                )
            }
            None => {
                let vendor = self.locate_bundle(project, tv, pin, opts).await?;
                (vendor.url, vendor.digest)
            }
        };
        let text = crate::packslip::fetch_text(&url).await?;
        let actual = hex::encode(Sha256::digest(text.as_bytes()));
        for expected in vendor_digest
            .iter()
            .chain(stamp.and_then(|stamp| stamp.digest.as_ref()))
        {
            if &actual != expected {
                bail!(
                    "packslip:{project}@{}: manifest digest differs from signed list",
                    tv.version
                );
            }
        }
        let verified = verify_bundle(&text, pin, !opts.allow_unlogged(), &[])?;
        if verified.project != project || verified.version != tv.version {
            bail!(
                "packslip:{project}@{}: verified manifest project/version differs from discovery",
                tv.version
            );
        }
        let scheme = verified.scheme.to_string();
        let attested_by = verified.attested_by.to_string();
        packslip_pins::check(
            project,
            Observed {
                scheme: &scheme,

View on GitHub (pinned to 533346cc37)