{"record":{"id":"037ad0817b5804d0","repo":"multica-ai/multica","slug":"checksum-manifest-q-not-present-in-release","errorCode":null,"errorMessage":"checksum manifest %q not present in release","messagePattern":"checksum manifest %q not present in release","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/internal/cli/update.go","lineNumber":181,"sourceCode":"\t\t}\n\t}\n\n\tcandidates := strings.Join(releaseAssetCandidates(targetVersion, goos, goarch), \", \")\n\treturn nil, fmt.Errorf(\"no matching release asset for %s/%s (tried: %s)\", goos, goarch, candidates)\n}\n\n// findChecksumManifestAsset locates the GoReleaser-generated checksums.txt\n// among a release's assets. Required for the direct-download path's SHA-256\n// verification — if it is missing we refuse to replace the binary rather\n// than fall back to unverified install, because the auto-update poller runs\n// unattended and an unverified binary swap is a supply-chain risk.\nfunc findChecksumManifestAsset(assets []GitHubReleaseAsset) (*GitHubReleaseAsset, error) {\n\tfor i := range assets {\n\t\tif assets[i].Name == ChecksumManifestName {\n\t\t\treturn &assets[i], nil\n\t\t}\n\t}\n\treturn nil, fmt.Errorf(\"checksum manifest %q not present in release\", ChecksumManifestName)\n}\n\n// parseChecksumManifest reads a GoReleaser-style \"<sha256>  <filename>\"\n// manifest and returns the lowercase hex SHA-256 for assetName. Returns an\n// error if the asset is absent so a typo (or the wrong manifest from a\n// different release) fails closed rather than silently disabling\n// verification.\nfunc parseChecksumManifest(manifest []byte, assetName string) (string, error) {\n\tscanner := bufio.NewScanner(bytes.NewReader(manifest))\n\tfor scanner.Scan() {\n\t\tline := strings.TrimSpace(scanner.Text())\n\t\tif line == \"\" || strings.HasPrefix(line, \"#\") {\n\t\t\tcontinue\n\t\t}\n\t\tfields := strings.Fields(line)\n\t\t// GoReleaser's default separator is two spaces; some tools use one\n\t\t// or pad with tabs. strings.Fields handles all of those at once.\n\t\tif len(fields) < 2 {","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/internal/cli/update.go#L163-L199","documentation":"The direct-download update path requires the GoReleaser-generated checksums.txt asset so the downloaded archive can be SHA-256 verified before the binary is replaced. The release has no asset named checksums.txt, and the code intentionally fails closed instead of installing unverified — the auto-updater runs unattended and an unverified binary swap is a supply-chain risk.","triggerScenarios":"Fetching a release that was published without GoReleaser's checksum step (manually uploaded assets, draft release, or a release config that disables checksums) and then attempting the verified download/update.","commonSituations":"Hand-built releases where maintainers uploaded only the archives; a .goreleaser.yaml with checksum.name_template removed or set to something else; enterprise mirrors that strip auxiliary files when re-hosting releases.","solutions":["Publish the release through GoReleaser with its default checksums.txt generation enabled","If mirroring releases, mirror checksums.txt alongside the archives","As an end user, update from the official multica-ai/multica releases rather than the stripped source","Do not attempt to bypass verification by patching the check — the failure closed is the security control"],"exampleFix":"# .goreleaser.yaml — before: checksums disabled\nchecksum:\n  disable: true\n\n# after: default checksum generation (asset name checksums.txt)\n# (omit the checksum section entirely, or:)\nchecksum:\n  name_template: '{{ .ProjectName }}_{{ .Version }}_checksums.txt' # must match ChecksumManifestName if customized\n# simplest: checksum:\n#   name_template: 'checksums.txt'","handlingStrategy":"validation","validationCode":"hasChecksum := false\nfor _, a := range release.Assets {\n\tif a.Name == \"checksums.txt\" { hasChecksum = true }\n}\nif !hasChecksum {\n\t// refuse verified download; use official releases instead\n}","typeGuard":"func hasChecksumManifest(assets []cli.GitHubReleaseAsset) bool {\n\tfor _, a := range assets {\n\t\tif a.Name == cli.ChecksumManifestName { return true }\n\t}\n\treturn false\n}","tryCatchPattern":"if err := downloadAndVerify(release); err != nil {\n\tif strings.Contains(err.Error(), \"checksum manifest\") {\n\t\t// release is not safely consumable; skip this update and report\n\t}\n}","preventionTips":["Always publish releases with GoReleaser checksums enabled","Never strip checksums.txt when mirroring releases","Treat a missing manifest as a hard stop, not a warning"],"tags":["release","security","checksum","supply-chain","go"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}