{"record":{"id":"bda040e3ce3914d8","repo":"Hmbown/CodeWhale","slug":"label-contains-duplicate-checksum-rows-for-na","errorCode":null,"errorMessage":"${label} contains duplicate checksum rows for ${name}","messagePattern":"(.+?) contains duplicate checksum rows for (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/release/assemble-release-assets.js","lineNumber":44,"sourceCode":"  const hash = crypto.createHash(\"sha256\");\n  hash.update(await fs.readFile(filePath));\n  return hash.digest(\"hex\");\n}\n\nfunction parseChecksumManifest(content, label) {\n  const checksums = new Map();\n  for (const line of content.split(/\\r?\\n/)) {\n    const trimmed = line.trim();\n    if (!trimmed) {\n      continue;\n    }\n    const match = trimmed.match(/^([a-fA-F0-9]{64})\\s+\\*?(.+)$/);\n    if (!match) {\n      throw new Error(`${label} contains an invalid checksum row: ${trimmed}`);\n    }\n    const name = match[2];\n    if (checksums.has(name)) {\n      throw new Error(`${label} contains duplicate checksum rows for ${name}`);\n    }\n    checksums.set(name, match[1].toLowerCase());\n  }\n  return checksums;\n}\n\nfunction assertExactNames(actualNames, expectedNames, label) {\n  const actual = new Set(actualNames);\n  const expected = new Set(expectedNames);\n  const missing = expectedNames.filter((name) => !actual.has(name));\n  const unexpected = actualNames.filter((name) => !expected.has(name));\n  if (missing.length > 0 || unexpected.length > 0 || actual.size !== actualNames.length) {\n    throw new Error(\n      `${label} does not match the authoritative inventory` +\n        `${missing.length > 0 ? `; missing: ${missing.join(\", \")}` : \"\"}` +\n        `${unexpected.length > 0 ? `; unexpected: ${unexpected.join(\", \")}` : \"\"}` +\n        `${actual.size !== actualNames.length ? \"; duplicate basenames are present\" : \"\"}`,\n    );","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/8880682c63083a91624de936797efa3ce9e498fd/scripts/release/assemble-release-assets.js#L26-L62","documentation":"parseChecksumManifest() found two rows for the same filename in a checksum manifest and refuses the ambiguous input. The Map-based parse keeps one digest per basename, so a duplicate row means the manifest was concatenated, double-generated, or edited and cannot attest a single hash per asset. The conflicting basename is named in the message.","triggerScenarios":"Concatenating two manifest files covering overlapping assets; a generator appending instead of overwriting; copy-paste duplication while hand-editing; the same bundle listed under both plain and *-prefixed forms that normalize to the same name.","commonSituations":"Merging manifests from parallel CI jobs without dedupe; a buggy custom packaging script appending rows on retry; manual re-addition of a 'missing' row that was actually present.","solutions":["Remove the duplicate row so each basename appears exactly once, keeping the row whose hash matches the actual file (verify with sha256sum)","Prefer regenerating the manifest via the assemble script instead of editing it","If two artifacts legitimately share a basename, rename one — the release inventory requires unique basenames (assertExactNames also rejects duplicates)"],"exampleFix":"# before\n9d86...  codewhale-x86_64.tar.gz\n4e97...  codewhale-x86_64.tar.gz   # duplicate row\n\n# after\n9d86...  codewhale-x86_64.tar.gz","handlingStrategy":"validation","validationCode":"function findDuplicateManifestRows(content) {\n  const seen = new Set();\n  const duplicates = [];\n  for (const line of content.split(/\\r?\\n/)) {\n    const match = line.trim().match(/^[a-fA-F0-9]{64}\\s+\\*?(.+)$/);\n    if (!match) continue;\n    if (seen.has(match[2])) duplicates.push(match[2]);\n    seen.add(match[2]);\n  }\n  return duplicates;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never concatenate manifests from parallel jobs — merge with dedupe by basename or generate one manifest at the end","When regenerating, overwrite the manifest file rather than appending","Enforce unique artifact basenames in the build config so duplicates cannot arise downstream"],"tags":["release","checksum","manifest","duplicates","validation"],"backgroundTag":null,"analyzedSha":"8880682c63083a91624de936797efa3ce9e498fd","analyzedAt":"2026-08-16T11:31:27.956Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}