kubernetes/kops · error
invalid %q hash - unexpected length %d
Error message
invalid %q hash - unexpected length %d
What it means
FromString validates that a hash string for a given algorithm has the expected length (MD5=32, SHA1=40, SHA256=64) before hex-decoding it. This error is thrown when the string length does not match the declared algorithm's digest size. It indicates the hash string was truncated, padded, or paired with the wrong algorithm prefix.
Source
Thrown at util/pkg/hashing/hash.go:87
klog.Exitf("Unknown hash algorithm: %v", ha)
return nil
}
func (ha HashAlgorithm) FromString(s string) (*Hash, error) {
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) {View on GitHub (pinned to 4c8573c808)
Solutions
- Count the hash string length and use the matching algorithm prefix (32=md5, 40=sha1, 64=sha256)
- Recompute the hash with `sha256sum <file>` and replace the value in the asset/manifest
- If the algorithm is unknown, use FromString on the bare string (hash.go:106) which infers the algorithm from length
Example fix
// before
h, err := hashing.HashAlgorithmSHA256.FromString("d41d8cd98f00b204e9800998ecf8427e") // 32 chars
// after
h, err := hashing.HashAlgorithmMD5.FromString("d41d8cd98f00b204e9800998ecf8427e") Defensive patterns
Strategy: validation
Validate before calling
func isValidHashFor(algo hashing.HashAlgorithm, s string) bool {
var l int
switch algo {
case hashing.HashAlgorithmMD5: l = 32
case hashing.HashAlgorithmSHA1: l = 40
case hashing.HashAlgorithmSHA256: l = 64
default: return false
}
if len(s) != l { return false }
_, err := hex.DecodeString(s)
return err == nil
} Type guard
func isHex(s string) bool {
_, err := hex.DecodeString(s)
return err == nil
} Try / catch
h, err := hashing.HashAlgorithmSHA256.FromString(s)
if err != nil {
if strings.Contains(err.Error(), "unexpected length") {
return fmt.Errorf("hash %q is not a sha256 digest (want 64 hex chars)", s)
}
return err
} Prevention
- Generate hashes with sha256sum/sha1sum/md5sum so length and hex-ness are guaranteed
- Keep algorithm name and hash value paired in one structure, never edited separately
- Validate asset manifests at load time before use
- Never hand-edit hash values; regenerate them from the artifact
When it happens
Trigger: Calling HashAlgorithm.FromString (or FromString via length-prefixed paths like buildFileAsset, FindCNIAssets, Add) with e.g. hashAlgorithmSHA256.FromString("abc123...") where the string is 40 chars instead of 64, or a partially copied/truncated hash in an asset manifest.
Common situations: Manually editing cluster spec assets or file URLs and pasting a SHA1 hash into a sha256 field; copying hashes from docs for a different algorithm version; downloading truncated hash files; CNI manifest hashes updated for one algorithm but not the other.
Related errors
- addon %q manifest hash was not populated
- unknown hash algorithm: %q
- invalid hash %q - not hex
- 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/021bf7dbab0e9a9b.
Report an issue: GitHub.