Hmbown/CodeWhale · error · Error

${label} contains an invalid checksum row: ${trimmed}

Error message

${label} contains an invalid checksum row: ${trimmed}

What it means

Raised by parseChecksumManifest() in scripts/release/assemble-release-assets.js while reading CHECKSUM_MANIFEST or BUNDLE_CHECKSUM_MANIFEST: a non-empty line did not match the strict sha256sum row format ^([a-fA-F0-9]{64})\s+\*?(.+)$ — exactly 64 hex characters, whitespace, an optional binary-mode '*', then a filename. The offending line is reproduced verbatim in the message.

Source

Thrown at scripts/release/assemble-release-assets.js:40

  ].join("\n");
}

async function sha256(filePath) {
  const hash = crypto.createHash("sha256");
  hash.update(await fs.readFile(filePath));
  return hash.digest("hex");
}

function parseChecksumManifest(content, label) {
  const checksums = new Map();
  for (const line of content.split(/\r?\n/)) {
    const trimmed = line.trim();
    if (!trimmed) {
      continue;
    }
    const match = trimmed.match(/^([a-fA-F0-9]{64})\s+\*?(.+)$/);
    if (!match) {
      throw new Error(`${label} contains an invalid checksum row: ${trimmed}`);
    }
    const name = match[2];
    if (checksums.has(name)) {
      throw new Error(`${label} contains duplicate checksum rows for ${name}`);
    }
    checksums.set(name, match[1].toLowerCase());
  }
  return checksums;
}

function assertExactNames(actualNames, expectedNames, label) {
  const actual = new Set(actualNames);
  const expected = new Set(expectedNames);
  const missing = expectedNames.filter((name) => !actual.has(name));
  const unexpected = actualNames.filter((name) => !expected.has(name));
  if (missing.length > 0 || unexpected.length > 0 || actual.size !== actualNames.length) {
    throw new Error(
      `${label} does not match the authoritative inventory` +

View on GitHub (pinned to 8880682c63)

Solutions

  1. Regenerate the manifest in standard sha256sum form '<64-hex> <name>' — the assemble step writes it itself, so avoid manual edits entirely
  2. Delete or fix the exact line quoted in the message, then re-run node scripts/release/assemble-release-assets.js --verify ASSET_DIR
  3. If the file arrived via CI download, re-download it: truncation and corruption show up as malformed rows

Example fix

# before (SHA1_SUMS.txt)
d3f2ba81b4c05e9a...  codewhale-x86_64.tar.gz   # 40 hex chars -> invalid row

# after (sha256sum format)
9d86f4b1c0e2a7...64-hex-total...  codewhale-x86_64.tar.gz
Defensive patterns

Strategy: validation

Validate before calling

const ROW = /^[a-fA-F0-9]{64}\s+\*?(.+)$/;
function manifestRowsAreValid(content) {
  return content
    .split(/\r?\n/)
    .filter((line) => line.trim() !== "")
    .every((line) => ROW.test(line.trim()));
}
// run before invoking --verify:
if (!manifestRowsAreValid(await fs.readFile(manifestPath, "utf8"))) {
  throw new Error(`manifest at ${manifestPath} has malformed rows`);
}

Prevention

When it happens

Trigger: A row carrying an md5/sha1 digest (32/40 hex chars); filename placed before the hash; no whitespace between hash and name; a stray header or comment line ('# sha256 sums'); a row truncated or wrapped by an editor; a line pasted from a different manifest format.

Common situations: Regenerating the manifest with a different tool (md5sum, sha1sum, or name-first column order); hand-editing the manifest after assembly; a truncated CI artifact download producing garbage lines; mixing another product's manifest into the asset directory.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@8880682c63 (2026-08-16). Data as JSON: /api/errors/3276e02700dbf626. Report an issue: GitHub.