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

  1. Re-download/re-fetch the artifact and retry — the most common cause is a truncated or corrupted transfer.
  2. Verify the digest against the upstream publisher's signed manifest to confirm which side is stale.
  3. If the artifact legitimately changed, update the expectedDigest to the freshly computed value and re-run.
  4. 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

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


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)