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

  1. Count the hash string length and use the matching algorithm prefix (32=md5, 40=sha1, 64=sha256)
  2. Recompute the hash with `sha256sum <file>` and replace the value in the asset/manifest
  3. 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

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


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/021bf7dbab0e9a9b. Report an issue: GitHub.