{"record":{"id":"d953e33935601d78","repo":"kubernetes/kops","slug":"cannot-determine-algorithm-for-hash-length-d","errorCode":null,"errorMessage":"cannot determine algorithm for hash length: %d","messagePattern":"cannot determine algorithm for hash length: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/pkg/hashing/hash.go","lineNumber":122,"sourceCode":"\nfunc FromString(s string) (*Hash, error) {\n\tfor _, ha := range []HashAlgorithm{HashAlgorithmMD5, HashAlgorithmSHA1, HashAlgorithmSHA256} {\n\t\tprefix := fmt.Sprintf(\"%s:\", ha)\n\t\tif strings.HasPrefix(s, prefix) {\n\t\t\treturn ha.FromString(s[len(prefix):])\n\t\t}\n\t}\n\n\tvar ha HashAlgorithm\n\tswitch len(s) {\n\tcase 32:\n\t\tha = HashAlgorithmMD5\n\tcase 40:\n\t\tha = HashAlgorithmSHA1\n\tcase 64:\n\t\tha = HashAlgorithmSHA256\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"cannot determine algorithm for hash length: %d\", len(s))\n\t}\n\n\treturn ha.FromString(s)\n}\n\nfunc (ha HashAlgorithm) Hash(r io.Reader) (*Hash, error) {\n\thasher := ha.NewHasher()\n\t_, err := copyToHasher(hasher, r)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error while hashing resource: %v\", err)\n\t}\n\treturn &Hash{Algorithm: ha, HashValue: hasher.Sum(nil)}, nil\n}\n\nfunc (ha HashAlgorithm) HashFile(p string) (*Hash, error) {\n\tf, err := os.OpenFile(p, os.O_RDONLY, 0)\n\tif err != nil {\n\t\tif os.IsNotExist(err) {","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/util/pkg/hashing/hash.go#L104-L140","documentation":"The bare-string FromString infers the hash algorithm purely from string length: 32=MD5, 40=SHA1, 64=SHA256. This error is thrown when the string's length matches none of those sizes. It is a guard against feeding arbitrary or corrupted strings into hash-based lookups.","triggerScenarios":"Calling hashing.FromString(\"...\") (the length-inference entry point) with a string of length 0, 33, 56, or 128 — e.g. an empty hash variable, a SHA-512 value, or a URL accidentally passed instead of a checksum.","commonSituations":"Asset/PKI lookups where the hash field was never populated (empty string); switching to SHA-512 in custom tooling; concatenating algorithm name and hash so length is off; reading a hash file that includes a trailing newline handled elsewhere.","solutions":["Ensure the hash string is exactly 32, 40, or 64 characters long","Trim whitespace/newlines and remove any algorithm prefix before calling FromString","If using SHA-512 or another size, call the explicit HashAlgorithm's FromString after extending the switch, rather than the length-inferring variant"],"exampleFix":"// before\nh, err := hashing.FromString(hashWithPrefix) // \"sha256:abc...\" -> wrong length\n// after\nh, err := hashing.HashAlgorithmSHA256.FromString(strings.TrimPrefix(hashWithPrefix, \"sha256:\"))","handlingStrategy":"validation","validationCode":"func hashable(s string) bool {\n\ts = strings.TrimSpace(s)\n\tswitch len(s) { case 32, 40, 64: return isHex(s) }\n\treturn false\n}\nif !hashable(s) { return fmt.Errorf(\"hash must be 32, 40 or 64 hex chars, got %d\", len(strings.TrimSpace(s))) }","typeGuard":"func isKnownHashLength(s string) bool {\n\tswitch len(strings.TrimSpace(s)) {\n\tcase 32, 40, 64:\n\t\treturn true\n\t}\n\treturn false\n}","tryCatchPattern":"h, err := hashing.FromString(strings.TrimSpace(raw))\nif err != nil {\n\tif strings.Contains(err.Error(), \"cannot determine algorithm\") {\n\t\treturn fmt.Errorf(\"input %q (len %d) is not an md5/sha1/sha256 digest\", raw, len(raw))\n\t}\n\treturn err\n}","preventionTips":["Check the hash variable is non-empty before calling FromString","Trim whitespace and strip algorithm prefixes first","Use the explicit HashAlgorithm.FromString when the algorithm is known","Reject SHA-512/other digests at input validation rather than at hashing time"],"tags":["hashing","validation","algorithm-detection"],"backgroundTag":"hash-length-mismatch","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}