henrygd/beszel · error
invalid SHA-256 release digest %q
Error message
invalid SHA-256 release digest %q
What it means
The hex portion after "sha256:" must decode cleanly and be exactly 32 bytes (sha256.Size, i.e. 64 hex characters). If hex.DecodeString fails (odd length or non-hex characters) or the decoded length differs, the digest is malformed for SHA-256 and verification aborts before touching the file.
Source
Thrown at internal/ghupdate/checksum.go:24
"encoding/hex"
"fmt"
"io"
"os"
"strings"
)
func verifyAssetChecksum(path, digest string) error {
algorithm, expectedHex, ok := strings.Cut(digest, ":")
if !ok || algorithm == "" || expectedHex == "" {
return fmt.Errorf("invalid release digest %q", digest)
}
if !strings.EqualFold(algorithm, "sha256") {
return fmt.Errorf("unsupported release digest algorithm %q", algorithm)
}
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 nilView on GitHub (pinned to b38fb7dafa)
Solutions
- Regenerate the digest with `sha256sum <asset>` and publish exactly the 64 hex characters after the "sha256:" prefix.
- Strip whitespace, quotes, and any "0x" prefix from the digest string before publishing it in release metadata.
- If the release JSON comes from a mirror, verify it passes through the original GitHub digest field unmodified.
Example fix
// before — truncated/odd-length hex digest := "sha256:3f2a9c" // 3 bytes, fails length check // after digest := "sha256:3f2a9c...e4" // full 64 hex chars from sha256sum
Defensive patterns
Strategy: validation
Validate before calling
hexPart := strings.SplitN(asset.Digest, ":", 2)[1]
if len(hexPart) != 64 {
return fmt.Errorf("digest hex must be 64 chars, got %d", len(hexPart))
}
if _, err := hex.DecodeString(hexPart); err != nil {
return fmt.Errorf("digest is not valid hex: %v", err)
} Try / catch
updated, err := ghupdate.Update(cfg)
if err != nil && strings.Contains(err.Error(), "invalid SHA-256 release digest") {
log.Printf("publisher's digest is malformed (%v); regenerate with sha256sum and republish", err)
} Prevention
- Generate digests mechanically with `sha256sum <asset>` — never by hand.
- Trim whitespace and quotes before embedding digests in release metadata.
- Add CI validation that digests match ^sha256:[0-9a-f]{64}$.
When it happens
Trigger: ghupdate.Update -> update -> verifyAssetChecksum with a digest whose hex part is truncated, contains non-hex characters (e.g. "0x" prefixes, whitespace, uppercase OK but stray chars not), or is 56/128 chars because the publisher hashed with a different length output.
Common situations: Hand-edited checksum files; copy-paste that dropped characters; scripts that prefix hashes with "0x"; digests copied from sha1 (40 chars) or sha512 (128 chars) outputs.
Related errors
- invalid release digest %q
- unsupported release digest algorithm %q
- unsupported hash length: %d (expected 40 for SHA1 or 64 for
- failed to open release for checksum verification: %w
- failed to calculate release checksum: %w
AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31).
Data as JSON: /api/errors/93761d52904dd1e6.
Report an issue: GitHub.