{"record":{"id":"c74d41082f708ae3","repo":"JuliusBrussee/caveman","slug":"duplicate-checksum-manifest-entry-filename","errorCode":null,"errorMessage":"duplicate checksum manifest entry: ${filename}","messagePattern":"duplicate checksum manifest entry: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cli/src/index.ts","lineNumber":2279,"sourceCode":"  if (!manifest || manifest.release !== BINARY_RELEASE) return null;\n  const installed: InstalledBinary[] = [];\n  for (const name of INSTALL_BINARIES) {\n    const expected = manifest.artifacts[name];\n    const path = join(binDir, binaryInstallFilename(name));\n    if (!expected || sha256File(path) !== expected) return null;\n    installed.push({ name, path, sha256: expected, status: \"already installed\" });\n  }\n  return installed;\n}\n\nfunction parseSignedChecksums(raw: string): Map<string, string> {\n  const checksums = new Map<string, string>();\n  for (const line of raw.split(\"\\n\")) {\n    if (!line) continue;\n    const match = line.match(/^([a-f0-9]{64})  ([A-Za-z0-9._-]+)$/);\n    if (!match) throw new Error(`invalid checksum manifest line: ${JSON.stringify(line)}`);\n    const filename = match[2]!;\n    if (checksums.has(filename)) throw new Error(`duplicate checksum manifest entry: ${filename}`);\n    checksums.set(filename, match[1]!);\n  }\n  return checksums;\n}\n\nfunction verifyChecksumSignature(checksums: string, signature: string): boolean {\n  try {\n    const bundle = JSON.parse(signature) as {\n      mediaType?: unknown;\n      messageSignature?: {\n        messageDigest?: { algorithm?: unknown; digest?: unknown };\n        signature?: unknown;\n      };\n    };\n    if (bundle.mediaType !== \"application/vnd.dev.sigstore.bundle.v0.3+json\") return false;\n    if (bundle.messageSignature?.messageDigest?.algorithm !== \"SHA2_256\") return false;\n    if (typeof bundle.messageSignature.messageDigest.digest !== \"string\") return false;\n    if (typeof bundle.messageSignature.signature !== \"string\") return false;","sourceCodeStart":2261,"sourceCodeEnd":2297,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/packages/cli/src/index.ts#L2261-L2297","documentation":"parseSignedChecksums builds a Map keyed by filename and throws if the same filename appears twice in the manifest. Duplicate entries make the signature verification ambiguous, so the whole manifest is rejected.","triggerScenarios":"A checksum manifest generated by concatenating two manifest files (or running sha256sum twice with append), producing the same filename on two lines.","commonSituations":"CI scripts doing `sha256sum * >> checksums.txt` on retries; merging an updated manifest into an old one without deduplication.","solutions":["Regenerate the manifest in one pass (sha256sum * > checksums.txt) instead of appending.","Deduplicate with `awk '!seen[$2]++' checksums.txt` after confirming entries agree.","Diff the two merged manifests and keep only the current release's entries."],"exampleFix":"// before (appended twice)\nabc...  cave-darwin-arm64\ndef...  cave-darwin-arm64\n\n// after\nabc...  cave-darwin-arm64","handlingStrategy":"validation","validationCode":"const names = raw.split('\\n').filter(Boolean).map(l => l.match(/^[a-f0-9]{64}  ([A-Za-z0-9._-]+)$/)?.[1]);\nconst dupes = names.filter((n, i) => n && names.indexOf(n) !== i);\nif (dupes.length) throw new Error(`duplicate manifest entries: ${[...new Set(dupes)].join(', ')}`);","typeGuard":null,"tryCatchPattern":"try {\n  verify(manifest);\n} catch (error) {\n  if (error.message.startsWith('duplicate checksum manifest entry')) {\n    console.error(`${error.message}\\nRegenerate the manifest in a single pass instead of appending.`);\n  } else throw error;\n}","preventionTips":["Write manifests with `>` (overwrite), never `>>` (append)","Deduplicate with `awk '!seen[$2]++'` when merging manifests","Regenerate the whole manifest after adding or updating binaries"],"tags":["checksums","parsing","validation"],"backgroundTag":"checksum-mismatch","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}