{"record":{"id":"4997dd502a799bbf","repo":"henrygd/beszel","slug":"failed-to-calculate-release-checksum-w","errorCode":null,"errorMessage":"failed to calculate release checksum: %w","messagePattern":"failed to calculate release checksum: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/ghupdate/checksum.go","lineNumber":35,"sourceCode":"\t}\n\tif !strings.EqualFold(algorithm, \"sha256\") {\n\t\treturn fmt.Errorf(\"unsupported release digest algorithm %q\", algorithm)\n\t}\n\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":17,"sourceCodeEnd":44,"githubUrl":"https://github.com/henrygd/beszel/blob/b38fb7dafa60812cc22e6a84ce313e94f1ce0a32/internal/ghupdate/checksum.go#L17-L44","documentation":"After opening the file, the library streams it into a sha256 hash via io.Copy. If reading fails mid-stream — disk I/O error, file truncated/removed while reading — the read error is wrapped with this message. This is about failing to compute the checksum, not a mismatch.","triggerScenarios":"ghupdate.Update -> update -> verifyAssetChecksum when io.Copy(hash, file) returns an error: hardware/disk I/O failure, file deleted or truncated by another process during hashing, or an fs error caused by a failing mount.","commonSituations":"Failing or full disks; network filesystems (NFS/CIFS) dropping the file mid-read; concurrent cleanup of the temp release directory; corrupted filesystem after a crash.","solutions":["Re-run the update; if the temp dir is on unstable storage, set Config.DataDir to a local reliable path.","Check `dmesg`/system logs for disk I/O errors and run fsck or replace failing hardware.","Ensure nothing concurrently deletes or truncates files in DataDir while the updater runs.","Verify free disk space with `df -h` and the health of the mount hosting DataDir."],"exampleFix":"// before\nUpdate(ghupdate.Config{DataDir: \"/mnt/nfs/shared\"}) // flaky NFS reads\n// after\nUpdate(ghupdate.Config{DataDir: \"/var/lib/beszel\"}) // local disk","handlingStrategy":"retry","validationCode":"if fi, err := os.Stat(cfg.DataDir); err == nil {\n    if st, err := os.Statfs(cfg.DataDir); err == nil && st.Bavail == 0 {\n        return errors.New(\"DataDir filesystem is full; free space before updating\")\n    }\n}","typeGuard":null,"tryCatchPattern":"var updated bool\nvar lastErr error\nfor i := 0; i < 3; i++ {\n    updated, lastErr = ghupdate.Update(cfg)\n    if lastErr == nil || !strings.Contains(lastErr.Error(), \"failed to calculate release checksum\") {\n        break\n    }\n    time.Sleep(time.Second) // transient I/O error; retry\n}","preventionTips":["Monitor disk health (SMART) and free space on the volume hosting DataDir.","Avoid running the updater concurrently with other processes that touch DataDir.","Prefer local disks over NFS/CIFS for DataDir."],"tags":["filesystem","io","checksum","disk"],"backgroundTag":"disk-io-error","analyzedSha":"b38fb7dafa60812cc22e6a84ce313e94f1ce0a32","analyzedAt":"2026-08-31T15:10:10.149Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}