affaan-m/ECC · critical · Error
digest mismatch: expected , got .
Error message
${label} digest mismatch: expected ${expectedDigest}, got ${actual}. What it means
After confirming the expected digest string is well-formed, assertDigest computes the actual SHA-256 of the supplied bytes and compares it to the expected value. This error means the content does not match its declared digest — the data is corrupted, tampered with, or the wrong file was supplied. It is the library's supply-chain integrity check.
Solutions
- Re-download/re-fetch the artifact and retry — the most common cause is a truncated or corrupted transfer.
- Verify the digest against the upstream publisher's signed manifest to confirm which side is stale.
- If the artifact legitimately changed, update the expectedDigest to the freshly computed value and re-run.
- Clear any intermediate cache or mirror that may have served a stale blob.
Example fix
// before
assertDigest(archiveBytes, manifestDigest, 'manifest');
// after
const actual = `sha256:${crypto.createHash('sha256').update(archiveBytes).digest('hex')}`;
if (actual !== manifestDigest) {
console.error(`stale artifact? expected ${manifestDigest}, got ${actual}; refetching...`);
archiveBytes = await refetchAndVerify();
}
assertDigest(archiveBytes, manifestDigest, 'manifest'); Defensive patterns
Strategy: validation
Validate before calling
const actual = `sha256:${crypto.createHash('sha256').update(bytes).digest('hex')}`;
if (actual !== expectedDigest) throw new Error(`artifact corrupted: ${actual} != ${expectedDigest}; refetch`); Type guard
null
Try / catch
try { installNasiko(opts); } catch (e) { if (e.message.includes('digest mismatch')) { await refetchArtifact(); return installNasiko(opts); } throw e; } Prevention
- Always pin artifacts by digest, never by mutable tag.
- Verify downloads immediately after fetch, before caching.
- Re-download once automatically on mismatch before surfacing the error.
When it happens
Trigger: installNasiko passes bytes (e.g. a downloaded layer or archive) plus its declared digest to assertDigest, and sha256(bytes) !== expectedDigest. E.g. a partially downloaded file, a re-pushed image tag, or an edited manifest.
Common situations: Interrupted downloads, a registry tag was overwritten with new content, a proxy or mirror rewrote the artifact, or the manifest was hand-edited without updating the digest.
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
- artifact SHA-256 does not match receipt
- artifact SHA-256 mismatch
- candidate content address or canonical configuration is…
- harness health evidence integrity verification failed
- anchor evidence source duration is not bound to its receipt…
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/665aa726c2a27813.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/nasiko-release.js:57
function getQualifiedRelease(version, platform = process.platform, architecture = process.arch) {
if (!/^v\d+\.\d+\.\d+$/.test(String(version || ''))) {
throw new Error('Nasiko installation requires a pinned version such as v0.1.0; latest is not allowed.');
}
const normalized = normalizePlatform(platform, architecture);
const qualification = QUALIFIED_RELEASES[version]?.[`${normalized.os}/${normalized.arch}`];
if (!qualification) throw new Error(`Nasiko ${version} is not qualified for ${normalized.os}/${normalized.arch}.`);
return { version, ...normalized, ...qualification, license: LICENSE, sourceUrl: SOURCE_URL };
}
function digestBytes(bytes) {
return `sha256:${crypto.createHash('sha256').update(bytes).digest('hex')}`;
}
function assertDigest(bytes, expectedDigest, label) {
if (!SHA256_PATTERN.test(expectedDigest)) throw new Error(`${label} has an invalid expected digest.`);
const actual = digestBytes(bytes);
if (actual !== expectedDigest) throw new Error(`${label} digest mismatch: expected ${expectedDigest}, got ${actual}.`);
}
function validateManifest(bytes) {
let manifest;
try { manifest = JSON.parse(bytes.toString('utf8')); } catch (_error) { throw new Error('Nasiko manifest is not valid JSON.'); }
if (manifest.schemaVersion !== 2 || !Array.isArray(manifest.layers) || manifest.layers.length !== 1) {
throw new Error('Nasiko manifest must contain exactly one OCI layer.');
}
const layer = manifest.layers[0];
if (layer.mediaType !== 'application/gzip' || !SHA256_PATTERN.test(layer.digest)) {
throw new Error('Nasiko manifest layer is not a qualified gzip artifact.');
}
if (!Number.isSafeInteger(layer.size) || layer.size <= 0 || layer.size > MAX_ARCHIVE_BYTES) {
throw new Error('Nasiko manifest layer size is outside the allowed range.');
}
return { digest: layer.digest, size: layer.size };
}
View on GitHub (pinned to 8321021c54)