{"record":{"id":"97b56ee9063f525f","repo":"henrygd/beszel","slug":"release-checksum-mismatch-expected-s-got-s","errorCode":null,"errorMessage":"release checksum mismatch: expected %s, got %s","messagePattern":"release checksum mismatch: expected (.+?), got (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/ghupdate/checksum.go","lineNumber":39,"sourceCode":"\n\texpected, err := hex.DecodeString(expectedHex)\n\tif err != nil || len(expected) != sha256.Size {\n\t\treturn fmt.Errorf(\"invalid SHA-256 release digest %q\", digest)\n\t}\n\n\tfile, err := os.Open(path)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to open release for checksum verification: %w\", err)\n\t}\n\tdefer file.Close()\n\n\thash := sha256.New()\n\tif _, err := io.Copy(hash, file); err != nil {\n\t\treturn fmt.Errorf(\"failed to calculate release checksum: %w\", err)\n\t}\n\tactual := hash.Sum(nil)\n\tif !bytes.Equal(actual, expected) {\n\t\treturn fmt.Errorf(\"release checksum mismatch: expected %s, got %s\", expectedHex, hex.EncodeToString(actual))\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":21,"sourceCodeEnd":44,"githubUrl":"https://github.com/henrygd/beszel/blob/b38fb7dafa60812cc22e6a84ce313e94f1ce0a32/internal/ghupdate/checksum.go#L21-L44","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Simply retry the update — transient truncation during download is the most common cause.","Bypass any proxy/CDN cache or wait for the mirror to sync; try with UseMirror toggled to fetch from the other source.","Compare the 'got' hash against the official sha256sum published with the release to distinguish corruption from tampering.","If mismatches persist from your network, download the asset manually, verify its hash, and investigate the middlebox rewriting content."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"updated, err := ghupdate.Update(cfg)\nif err != nil && strings.Contains(err.Error(), \"release checksum mismatch\") {\n    log.Printf(\"download integrity check failed (%v); do NOT install manually — retry via a trusted network or wait for mirror sync\", err)\n}","preventionTips":["Never bypass or disable checksum verification to force an update.","Retry on a trusted network; caches and proxies are the usual culprit.","Keep mirrors in sync with upstream releases before pointing clients at them.","Treat persistent mismatches as a security incident and compare against the official sha256sum."],"tags":["checksum","integrity","security","download","self-update"],"backgroundTag":"checksum-mismatch","analyzedSha":"b38fb7dafa60812cc22e6a84ce313e94f1ce0a32","analyzedAt":"2026-08-31T15:10:10.149Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}