kubernetes/kops · error
invalid hash %q - not hex
Error message
invalid hash %q - not hex
What it means
FromString hex-decodes the hash string after a length check; this error is thrown when hex.DecodeString fails, meaning the string contains non-hexadecimal characters. Length was correct for the algorithm, but the content is not valid hex (e.g. contains 'g'-'z', spaces, or base64 data).
Source
Thrown at util/pkg/hashing/hash.go:92
var l int
switch ha {
case HashAlgorithmMD5:
l = 32
case HashAlgorithmSHA1:
l = 40
case HashAlgorithmSHA256:
l = 64
default:
return nil, fmt.Errorf("unknown hash algorithm: %q", ha)
}
if len(s) != l {
return nil, fmt.Errorf("invalid %q hash - unexpected length %d", ha, len(s))
}
hashValue, err := hex.DecodeString(s)
if err != nil {
return nil, fmt.Errorf("invalid hash %q - not hex", s)
}
return &Hash{Algorithm: ha, HashValue: hashValue}, nil
}
func MustFromString(s string) *Hash {
h, err := FromString(s)
if err != nil {
klog.Fatalf("FromString(%q) failed with %v", s, err)
}
return h
}
func FromString(s string) (*Hash, error) {
for _, ha := range []HashAlgorithm{HashAlgorithmMD5, HashAlgorithmSHA1, HashAlgorithmSHA256} {
prefix := fmt.Sprintf("%s:", ha)
if strings.HasPrefix(s, prefix) {
return ha.FromString(s[len(prefix):])
}View on GitHub (pinned to 4c8573c808)
Solutions
- Recompute the checksum with the standard tool (sha256sum/sha1sum/md5sum) which always outputs valid lowercase hex
- Strip any 'sha256:'/'sha1:' prefix and surrounding whitespace from the hash string
- If you have a base64 digest, convert it: `echo <b64> | base64 -d | xxd -p -c 64`
Example fix
// before
h, _ := hashing.HashAlgorithmSHA256.FromString(strings.TrimSpace("sha256:" + digest))
// after
h, _ := hashing.HashAlgorithmSHA256.FromString(strings.TrimPrefix(digest, "sha256:")) Defensive patterns
Strategy: validation
Validate before calling
func isHexDigest(s string) bool {
if s == "" { return false }
_, err := hex.DecodeString(s)
return err == nil
}
// call before: if !isHexDigest(digest) { return fmt.Errorf("digest must be hex") } Type guard
func isHexString(s string) bool {
for _, c := range s {
if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
return false
}
}
return len(s) > 0
} Try / catch
h, err := algo.FromString(s)
if err != nil {
if strings.Contains(err.Error(), "not hex") {
return fmt.Errorf("checksum %q contains non-hex characters; expected hex output of sha256sum", s)
}
return err
} Prevention
- Always source checksums from checksum tools or registries that emit hex
- Strip 'sha256:'/'sha1:' prefixes and whitespace before use
- Watch for base64 digests (contain +, /, =) — convert to hex first
- Lint manifest files for characters outside [0-9a-f] in hash fields
When it happens
Trigger: Calling HashAlgorithm.FromString with a string of the right length but containing non-hex characters, e.g. hashing.HashAlgorithmSHA1.FromString("zz11..."), or accidentally pasting a base64 digest instead of hex.
Common situations: Pasting a base64-encoded checksum (common in some registries) into a field that expects hex; typos like 'O' vs '0' or 'l' vs '1'; hashes with whitespace or prefix like 'sha256:' not stripped.
Related errors
- addon %q manifest hash was not populated
- unknown hash algorithm: %q
- invalid %q hash - unexpected length %d
- cannot determine algorithm for hash length: %d
- error hashing manifest: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/50d9a63256f56512.
Report an issue: GitHub.