hashicorp/terraform · error · ErrInvalidSHA256Hash
ErrInvalidSHA256Hash
ErrInvalidSHA256Hash
Error message
the value was not a valid SHA-256 hash
What it means
ErrInvalidSHA256Hash is a sentinel returned by SHA256FromHex when the supplied string cannot be decoded as hex, or decodes to a length other than sha256.Size (32 bytes / 64 hex chars). It guards the parser used to turn the textual SHA256SUMS lines into a SHA256Hash, so a malformed hash line bubbles up as 'failed to parse checksums' from ParseChecksums.
Source
Thrown at internal/releaseauth/hash.go:19
// Copyright IBM Corp. 2014, 2026
// SPDX-License-Identifier: BUSL-1.1
package releaseauth
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"errors"
"fmt"
"log"
)
// SHA256Hash represents a 256-bit SHA hash
type SHA256Hash [sha256.Size]byte
// ErrInvalidSHA256Hash is returned when the hash is invalid
var ErrInvalidSHA256Hash = errors.New("the value was not a valid SHA-256 hash")
// SHA256FromHex decodes a SHA256Hash from a hex string dump
func SHA256FromHex(hashHex string) (SHA256Hash, error) {
var result [sha256.Size]byte
hash, err := hex.DecodeString(hashHex)
if err != nil || len(hash) != sha256.Size {
return result, ErrInvalidSHA256Hash
}
if copy(result[:], hash) != sha256.Size {
panic("could not copy hash value")
}
return result, nil
}
// SHA256Checksums decodes a file generated by the sha256sum program
type SHA256Checksums map[string]SHA256HashView on GitHub (pinned to c9def3e214)
Solutions
- Re-fetch the genuine SHA256SUMS file from the publisher (hashicorp/releases) and ensure it is the verbatim `<64 lowercase hex> <name>` format.
- Validate each hash token is exactly 64 lowercase hex characters before parsing.
- If the sums come from a custom mirror, fix the mirror to serve the unmodified upstream file.
- Check the file wasn't CRLF-converted or re-encoded on the way through a proxy.
Example fix
// validate a hex hash before calling SHA256FromHex
func validSHA256Hex(s string) bool {
if len(s) != 64 { return false }
for _, r := range s {
if !((r >= '0' && r <= '9') || (r >= 'a' && r <= 'f')) { return false }
}
return true
} Defensive patterns
Strategy: validation
Validate before calling
// Validate hex before parsing.
func validSHA256Hex(s string) bool {
if len(s) != 64 { return false }
_, err := hex.DecodeString(s)
return err == nil
}
if !validSHA256Hex(token) { return errors.New("malformed sha256") } Type guard
func isInvalidSHA256Hash(err error) bool {
return errors.Is(err, releaseauth.ErrInvalidSHA256Hash)
} Try / catch
h, err := releaseauth.SHA256FromHex(raw)
if errors.Is(err, releaseauth.ErrInvalidSHA256Hash) {
// skip / reject the malformed sums line rather than aborting the whole file
continue
} Prevention
- Only consume verbatim SHA256SUMS files from the publisher.
- Sanitize sums through a custom mirror that preserves the canonical format.
- Unit-test your sums parser against the real upstream format.
When it happens
Trigger: Returned at internal/releaseauth/hash.go:26 when hex.DecodeString(hashHex) errors OR len(hash) != sha256.Size. ParseChecksums (line 51) wraps it: 'failed to parse checksums: %w'.
Common situations: A SHA256SUMS file that is not in the standard `<64-hex> <filename>` format (extra whitespace, wrong separator, base64). A truncated or hand-edited sums file. A sums file from a different algorithm (SHA1/MD5). A registry/mirror that reformatted the file. An empty or garbage response served in place of SHA256SUMS.
Related errors
- ErrChecksumDoesNotMatch
- must be eight hexadecimal digits
- invalid source address: %s
- can't use local directory %q as a module registry address
- hash string must start with a scheme keyword followed by a c
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/a737cce9eb7847f6.
Report an issue: GitHub.