{"record":{"id":"5de09b203199c360","repo":"jdx/mise","slug":"name-sha256-is-actual-the-packslip-says","errorCode":null,"errorMessage":"{name}: sha256 is {actual}, the packslip says {}","messagePattern":"(.+?): sha256 is (.+?), the packslip says (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/packslip.rs","lineNumber":244,"sourceCode":"                    };\n                    pr.set_message(format!(\"download {name}\"));\n                    file::create_dir_all(dest.parent().unwrap_or(&base))?;\n                    // The tool is installed by now and the asset is an extra:\n                    // one that cannot be fetched is reported, not fatal. One\n                    // that arrives with the wrong digest is another matter.\n                    if let Err(err) = HTTP\n                        .download_file_with_headers(url, &dest, &headers_for(url)?, Some(pr))\n                        .await\n                    {\n                        let _ = file::remove_all(&dest);\n                        warn!(\"{}: could not fetch {name}: {err}\", tv.style());\n                        continue;\n                    }\n                    let (actual, _) = packslip::digest_file(&dest)?;\n                    let expected = statement.digest_of(name);\n                    if expected != Some(actual.as_str()) {\n                        let _ = file::remove_all(&dest);\n                        bail!(\n                            \"{name}: sha256 is {actual}, the packslip says {}\",\n                            expected.unwrap_or(\"it is not a subject\")\n                        );\n                    }\n                }\n                // The archive and the unpacked skill are separate: an archive\n                // left by an earlier attempt still needs unpacking.\n                if resource.kind == \"skill\"\n                    && let Some(skill) = skill_name(resource)\n                {\n                    let dir = base.join(\"skills\").join(skill);\n                    // Like the other skill sources: a skill that cannot be\n                    // unpacked is reported, and the tool still installs. The\n                    // digest check above stays fatal.\n                    if !dir.join(\"SKILL.md\").is_file()\n                        && let Err(err) = unpack_skill(&dest, &dir, pr)\n                    {\n                        warn!(\"{}: could not unpack skill {skill}: {err}\", tv.style());","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/packslip.rs#L226-L262","documentation":"Thrown by packslip::fetch_files after downloading and unpacking an artifact: the file's computed sha256 does not match the digest declared in the signed packslip manifest. mise deletes the bad file and aborts, protecting against corrupted or tampered downloads.","triggerScenarios":"The downloaded artifact's sha256 differs from digest_of(name) in the packslip statement — either the digest is listed but wrong, or the file is not listed as a subject at all (message says 'it is not a subject').","commonSituations":"Stale mirror or CDN serving an old artifact version; interrupted/corrupt download; a project changed its release artifacts without updating the packslip; the file being verified was never declared in the packslip manifest.","solutions":["Retry the fetch to rule out a corrupted/truncated download","Purge the mise cache for this tool and retry so a fresh copy is downloaded","Check whether the project's release assets changed; regenerate or update the packslip if you maintain it","Ensure every file you expect is listed in the packslip's subject/digest list","Verify your network isn't serving content through a stale caching proxy"],"exampleFix":"// packslip before: stale digest for renamed artifact\n{\"name\":\"tool-1.2.3.tar.gz\",\"digest\":\"sha256:old...\"}\n// after: digest updated to match the released asset\n{\"name\":\"tool-1.2.3.tar.gz\",\"digest\":\"sha256:computed-from-release...\"}","handlingStrategy":"validation","validationCode":"// verify the expected digest against the packslip before fetching\nlet expected = statement.digest_of(name).ok_or_else(|| anyhow!(\"{name} not listed in packslip subjects\"))?;\nlet actual = sha256_hex(&downloaded_bytes);\nif expected != format!(\"sha256:{actual}\") {\n    bail!(\"refusing to install {name}: digest mismatch (got {actual}, want {expected})\");\n}","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().contains(\"the packslip says\") => {\n        eprintln!(\"artifact corrupted or packslip stale; purge cache and retry once\");\n        purge_cache_and_retry(e)\n    }\n    other => other,\n}","preventionTips":["Keep packslip digests in sync with upstream release assets","One retry with a purged cache distinguishes corruption from genuine mismatch","Download from the canonical source, not stale mirrors/CDNs","Re-generate packslips whenever a release's assets change"],"tags":["packslip","sha256","checksum","integrity","download"],"backgroundTag":"checksum-mismatch","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}