Hmbown/CodeWhale · critical · NonRetryableError
Checksum mismatch for
Error message
Checksum mismatch for ${assetName}${from}: expected ${expected}, got ${actual} What it means
After hashing the downloaded file, `verifyChecksum` compares the actual SHA-256 with the digest from the manifest. A mismatch means the bytes on disk differ from the published artifact — the download was corrupted, truncated, or tampered with — so the installer throws a NonRetryableError and explicitly refuses to retry, since re-fetching from the same broken source will not fix it.
Solutions
- Delete the cached/partial download and retry from a different network (the error is non-retryable by design, so change the source, not just re-run).
- Switch to the official GitHub Release source (unset CODEWHALE_RELEASE_BASE_URL / CODEWHALE_USE_CNB_MIRROR).
- Compare the file's sha256 manually (`sha256sum <file>`) against the manifest and re-download the asset.
- If you operate the mirror, restore the exact published artifact bytes that match SHA256SUMS.
- Check proxy/AV software that may rewrite downloaded binaries.
Defensive patterns
Strategy: retry
Try / catch
try {
await install();
} catch (err) {
if (err.message.startsWith('Checksum mismatch for')) {
// non-retryable by design: change source/network, purge cache, then retry once
await purgeCache();
await install({ source: 'official' });
} else throw err;
} Prevention
- Download over stable networks; avoid flaky proxies for large artifacts.
- Always verify checksums — never bypass the installer's verification.
- Prefer official release sources over third-party mirrors that may re-upload artifacts.
- Exclude installer downloads from AV/proxy rewriting.
When it happens
Trigger: sha256File(filePath) != checksums.get(assetName) after a completed download from the release/mirror source identified by sourceLabel.
Common situations: Flaky network or proxy truncating large tarballs; a mirror serving stale or re-uploaded (bit-different) artifacts; CDN cache poisoning; disk corruption; interrupted write not caught by size checks.
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
- Checksum manifest is missing
- Checksum manifest is missing
- Invalid checksum manifest line
- checksum manifest is missing
- The update checksum did not match. Your current app is…
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/001ddf98a4c32ad1.
Report an issue: GitHub.
Appendix: source
Thrown at npm/codewhale/scripts/install.js:1186
async function sha256File(filePath) {
const content = await readFile(filePath);
return crypto.createHash("sha256").update(content).digest("hex");
}
async function verifyChecksum(filePath, assetName, checksums, sourceLabel) {
const expected = checksums.get(assetName);
if (!expected) {
const from = sourceLabel ? ` from ${sourceLabel}` : "";
throw new NonRetryableError(`Checksum manifest is missing ${assetName}${from}`);
}
const actual = await sha256File(filePath);
if (actual !== expected) {
// Bytes are corrupted; another fetch is unlikely to help without a fix
// upstream. Mark non-retryable. Never mix a locked source's bytes with
// another source's manifest.
const from = sourceLabel ? ` from ${sourceLabel}` : "";
throw new NonRetryableError(
`Checksum mismatch for ${assetName}${from}: expected ${expected}, got ${actual}`,
);
}
}
async function checksumMatches(filePath, assetName, checksums) {
const expected = checksums.get(assetName);
if (!expected) {
throw new NonRetryableError(`Checksum manifest is missing ${assetName}`);
}
const actual = await sha256File(filePath);
return actual === expected;
}
function formatSourceReceipt(source, version) {
return [
`source=${source.id}`,
`label=${source.label}`,View on GitHub (pinned to 433685b202)