multica-ai/multica · error

checksum manifest %q not present in release

Error message

checksum manifest %q not present in release

What it means

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.

Source

Thrown at server/internal/cli/update.go:181

		}
	}

	candidates := strings.Join(releaseAssetCandidates(targetVersion, goos, goarch), ", ")
	return nil, fmt.Errorf("no matching release asset for %s/%s (tried: %s)", goos, goarch, candidates)
}

// findChecksumManifestAsset locates the GoReleaser-generated checksums.txt
// among a release's assets. Required for the direct-download path's SHA-256
// verification — if it is missing we refuse to replace the binary rather
// than fall back to unverified install, because the auto-update poller runs
// unattended and an unverified binary swap is a supply-chain risk.
func findChecksumManifestAsset(assets []GitHubReleaseAsset) (*GitHubReleaseAsset, error) {
	for i := range assets {
		if assets[i].Name == ChecksumManifestName {
			return &assets[i], nil
		}
	}
	return nil, fmt.Errorf("checksum manifest %q not present in release", ChecksumManifestName)
}

// parseChecksumManifest reads a GoReleaser-style "<sha256>  <filename>"
// manifest and returns the lowercase hex SHA-256 for assetName. Returns an
// error if the asset is absent so a typo (or the wrong manifest from a
// different release) fails closed rather than silently disabling
// verification.
func parseChecksumManifest(manifest []byte, assetName string) (string, error) {
	scanner := bufio.NewScanner(bytes.NewReader(manifest))
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if line == "" || strings.HasPrefix(line, "#") {
			continue
		}
		fields := strings.Fields(line)
		// GoReleaser's default separator is two spaces; some tools use one
		// or pad with tabs. strings.Fields handles all of those at once.
		if len(fields) < 2 {

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Publish the release through GoReleaser with its default checksums.txt generation enabled
  2. If mirroring releases, mirror checksums.txt alongside the archives
  3. As an end user, update from the official multica-ai/multica releases rather than the stripped source
  4. Do not attempt to bypass verification by patching the check — the failure closed is the security control

Example fix

# .goreleaser.yaml — before: checksums disabled
checksum:
  disable: true

# after: default checksum generation (asset name checksums.txt)
# (omit the checksum section entirely, or:)
checksum:
  name_template: '{{ .ProjectName }}_{{ .Version }}_checksums.txt' # must match ChecksumManifestName if customized
# simplest: checksum:
#   name_template: 'checksums.txt'
Defensive patterns

Strategy: validation

Validate before calling

hasChecksum := false
for _, a := range release.Assets {
	if a.Name == "checksums.txt" { hasChecksum = true }
}
if !hasChecksum {
	// refuse verified download; use official releases instead
}

Type guard

func hasChecksumManifest(assets []cli.GitHubReleaseAsset) bool {
	for _, a := range assets {
		if a.Name == cli.ChecksumManifestName { return true }
	}
	return false
}

Try / catch

if err := downloadAndVerify(release); err != nil {
	if strings.Contains(err.Error(), "checksum manifest") {
		// release is not safely consumable; skip this update and report
	}
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/037ad0817b5804d0. Report an issue: GitHub.