Hmbown/CodeWhale · error · NonRetryableError

Checksum manifest is missing

Error message

Checksum manifest is missing ${assetName}${from}

What it means

`verifyChecksum` looks up the downloaded asset's name in the parsed checksum map before hashing. If the manifest does not contain an entry for that asset, verification cannot proceed and the installer throws this NonRetryableError (the `from` suffix names the source/manifest origin). This is a data-integrity guard: the installer never verifies an asset it has no published digest for.

Solutions

  1. Make the manifest and asset come from the same release/version — align CODEWHALE_RELEASE_BASE_URL paths or clear the locked source.
  2. Re-run the install so a fresh manifest is fetched for the current version.
  3. If you own the mirror, regenerate SHA256SUMS to include all current asset names.
  4. Check for an installer/version upgrade where the asset naming matches the available manifests.

Example fix

// before (locked manifest URL from v1.2 while assets are v1.3)
CODEWHALE_RELEASE_BASE_URL=https://mirror.example.com/codewhale/v1.2
// after
CODEWHALE_RELEASE_BASE_URL=https://mirror.example.com/codewhale/v1.3
Defensive patterns

Strategy: validation

Validate before calling

const expected = checksums.get(assetName);
if (!expected) throw new Error(`Manifest does not list ${assetName}; align manifest and asset versions.`);

Try / catch

try {
  await install();
} catch (err) {
  if (err.message.startsWith('Checksum manifest is missing')) {
    // re-fetch a manifest for the same version as the assets
  } else throw err;
}

Prevention

When it happens

Trigger: Downloading an asset (e.g. codewhale-linux-x64.tar.gz) whose name is absent from the fetched manifest — version skew between the manifest URL and the asset URL, an asset renamed upstream, or a mirror serving a stale SHA256SUMS.

Common situations: A pinned manifest from an older release while the resolver picked a newer asset name; mirrors that regenerate assets without updating SHA256SUMS; custom CODEWHALE_RELEASE_BASE_URL with a partial manifest.

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 Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/4a24a6bd100614c4. Report an issue: GitHub.

Appendix: source

Thrown at npm/codewhale/scripts/install.js:1178

    const match = trimmed.match(/^([a-fA-F0-9]{64})\s+\*?(.+)$/);
    if (!match) {
      throw new NonRetryableError(`Invalid checksum manifest line: ${trimmed}`);
    }
    checksums.set(match[2], match[1].toLowerCase());
  }
  return checksums;
}

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}`);
  }

View on GitHub (pinned to 433685b202)