hashicorp/packer · error
invalid SHA256 checksum format for %s in SHA256SUMS
Error message
invalid SHA256 checksum format for %s in SHA256SUMS
What it means
expectedZipSHA256FromSums parses a SHA256SUMS file line by line. When it finds a line whose filename matches the target zip, it validates the first field is a valid 64-character lowercase hex SHA-256 digest via isValidSHA256Hex. If the matched line's hash field is not valid hex of length 64, it refuses to return it and throws this error to prevent verifying against a corrupt or malformed checksum.
Source
Thrown at provisioner/hcp-sbom/packer_release_fetch.go:190
func isValidSHA256Hex(s string) bool {
if len(s) != 64 {
return false
}
_, err := hex.DecodeString(s)
return err == nil
}
func expectedZipSHA256FromSums(sumsContent, fileName string) (string, error) {
for _, line := range strings.Split(sumsContent, "\n") {
fields := strings.Fields(strings.TrimSpace(line))
if len(fields) < 2 {
continue
}
candidateFileName := strings.TrimPrefix(fields[len(fields)-1], "*")
if candidateFileName == fileName {
hash := strings.ToLower(fields[0])
if !isValidSHA256Hex(hash) {
return "", fmt.Errorf("invalid SHA256 checksum format for %s in SHA256SUMS", fileName)
}
return hash, nil
}
}
return "", fmt.Errorf("checksum for %s not found in SHA256SUMS", fileName)
}
func fileSHA256(path string) (string, error) {
f, err := os.Open(path)
if err != nil {
return "", fmt.Errorf("failed to open %s for hashing: %w", path, err)
}
defer func() { _ = f.Close() }()
h := sha256.New()
if _, err := io.Copy(h, f); err != nil {
return "", fmt.Errorf("failed hashing %s: %w", path, err)
}View on GitHub (pinned to eb36e3c3e4)
Solutions
- Inspect the SHA256SUMS file (curl <shaSumsURL>) and check the line for the target zip; verify the first field is exactly 64 hex characters.
- Regenerate the checksums file on your mirror with sha256sum (format: '<64-hex-hash> <filename>').
- Ensure no proxy/transform is modifying the file (check for BOM or HTML error pages served with 200).
- Confirm the filename matched is the intended one — a coincidental match with a line in another format will trip this validation.
Example fix
// before: mirror serving malformed sums // abc123 packer_1.11.0_linux_amd64.zip // after: regenerate with sha256sum on the mirror // sha256sum packer_1.11.0_linux_amd64.zip >> packer_1.11.0_SHA256SUMS // -> a1b2c3...64hex... packer_1.11.0_linux_amd64.zip
Defensive patterns
Strategy: validation
Validate before calling
func validateSumsLine(line, fileName string) error {
fields := strings.Fields(strings.TrimSpace(line))
if len(fields) < 2 || strings.TrimPrefix(fields[len(fields)-1], "*") != fileName {
return nil
}
h := strings.ToLower(fields[0])
if len(h) != 64 {
return fmt.Errorf("hash field for %s is %d chars, want 64", fileName, len(h))
}
if _, err := hex.DecodeString(h); err != nil {
return fmt.Errorf("hash field for %s is not valid hex: %v", fileName, err)
}
return nil
} Type guard
func isValidSHA256Hex(s string) bool {
if len(s) != 64 {
return false
}
_, err := hex.DecodeString(s)
return err == nil
} Try / catch
expectedSHA, err := expectedZipSHA256FromSums(sumsContent, fileName)
if err != nil {
if strings.Contains(err.Error(), "invalid SHA256 checksum format") {
log.Printf("SHA256SUMS content corrupted for %s, refusing verify", fileName)
// fail fast: never verify against a malformed checksum
}
return err
} Prevention
- Generate SHA256SUMS with sha256sum so the format is '<64-hex> <filename>'.
- Serve checksum files as plain text (no BOM, no HTML error pages, no content transformation).
- Add a CI check that validates every line of your mirror's SHA256SUMS with a 64-hex regex.
- Never hand-edit checksum files.
When it happens
Trigger: The SHA256SUMS content contains a line ending with the exact zip filename, but fields[0] is not 64 hex characters — e.g. a truncated line, an MD5/other digest format, 'sha256 <hash>' with extra tokens shifting parsing, a binary/BOM-corrupted file, or a hand-edited checksums file.
Common situations: Serving SHA256SUMS from a custom/internal mirror generated with the wrong tool or checksum algorithm; a proxy mangling the file (encoding/BOM insertion); a stub test server with placeholder checksum values like 'xxx'; lines in an unexpected format such as '<hash> *file' with extra whitespace tokens.
Related errors
- hash %q: %w
- unsupported format: %s
- unsupported scope: %s (supported: squashed, all-layers)
- unsupported scope: %s
- empty response body for %s
AI-assisted analysis of hashicorp/packer@eb36e3c3e4 (2026-09-05).
Data as JSON: /api/errors/039e8eaf0e2488db.
Report an issue: GitHub.