henrygd/beszel · critical

release checksum mismatch: expected %s, got %s

Error message

release checksum mismatch: expected %s, got %s

What it means

The computed SHA-256 of the downloaded asset does not match the digest published on the release. The library deliberately fails closed: a mismatch means the download is corrupt, incomplete, or has been tampered with, so the update is aborted before extraction and the binary is never replaced. The error shows both the expected and actual hex digests for comparison.

Source

Thrown at internal/ghupdate/checksum.go:39

	expected, err := hex.DecodeString(expectedHex)
	if err != nil || len(expected) != sha256.Size {
		return fmt.Errorf("invalid SHA-256 release digest %q", digest)
	}

	file, err := os.Open(path)
	if err != nil {
		return fmt.Errorf("failed to open release for checksum verification: %w", err)
	}
	defer file.Close()

	hash := sha256.New()
	if _, err := io.Copy(hash, file); err != nil {
		return fmt.Errorf("failed to calculate release checksum: %w", err)
	}
	actual := hash.Sum(nil)
	if !bytes.Equal(actual, expected) {
		return fmt.Errorf("release checksum mismatch: expected %s, got %s", expectedHex, hex.EncodeToString(actual))
	}

	return nil
}

View on GitHub (pinned to b38fb7dafa)

Solutions

  1. Simply retry the update — transient truncation during download is the most common cause.
  2. Bypass any proxy/CDN cache or wait for the mirror to sync; try with UseMirror toggled to fetch from the other source.
  3. Compare the 'got' hash against the official sha256sum published with the release to distinguish corruption from tampering.
  4. If mismatches persist from your network, download the asset manually, verify its hash, and investigate the middlebox rewriting content.
Defensive patterns

Strategy: try-catch

Try / catch

updated, err := ghupdate.Update(cfg)
if err != nil && strings.Contains(err.Error(), "release checksum mismatch") {
    log.Printf("download integrity check failed (%v); do NOT install manually — retry via a trusted network or wait for mirror sync", err)
}

Prevention

When it happens

Trigger: ghupdate.Update -> update -> downloadFile -> verifyAssetChecksum when the downloaded archive's hash differs from the release digest: truncated/interrupted download that still returned HTTP 200, a proxy/CDN serving stale or modified content, a MITM, or the mirror serving an outdated asset while the digest points to a newer build.

Common situations: Corporate proxies caching an old asset; gh.beszel.dev or a custom mirror lagging behind GitHub; unstable network dropping bytes from a large tar.gz; an attacker substituting binaries (the case this check exists for).

Related errors


AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31). Data as JSON: /api/errors/97b56ee9063f525f. Report an issue: GitHub.