kubernetes/kops · error

not valid MD5 sum: %q

Error message

not valid MD5 sum: %q

What it means

AzureBlobPath.Hash returns the MD5 of a stored blob. Azure stores content MD5 as a base64 string; this code base64-decodes it before returning. If the stored md5Hash string is not valid base64 (or not 16 decoded bytes), the library refuses to produce a hash and throws `not valid MD5 sum: %q`.

Source

Thrown at util/pkg/vfs/azureblob.go:98

// PreferredHash returns the hash of the file contents, with the preferred hash algorithm.
func (p *AzureBlobPath) PreferredHash() (*hashing.Hash, error) {
	return p.Hash(hashing.HashAlgorithmMD5)
}

// Hash gets the hash, or nil if the hash cannot be (easily) computed.
func (p *AzureBlobPath) Hash(a hashing.HashAlgorithm) (*hashing.Hash, error) {
	if a != hashing.HashAlgorithmMD5 {
		return nil, nil
	}

	if p.md5Hash == "" {
		return nil, nil
	}

	md5Bytes, err := base64.StdEncoding.DecodeString(p.md5Hash)
	if err != nil {
		return nil, fmt.Errorf("not valid MD5 sum: %q", p.md5Hash)
	}

	return &hashing.Hash{Algorithm: hashing.HashAlgorithmMD5, HashValue: md5Bytes}, nil
}

// Path returns a string representing the full path.
func (p *AzureBlobPath) Path() string {
	return fmt.Sprintf("azureblob://%s/%s/%s", p.account, p.container, p.key)
}

// String implements fmt.Stringer; returns Path() so %s renders the full URL.
func (p *AzureBlobPath) String() string {
	return p.Path()
}

// Join returns a new path that joins the current path and given relative paths.
func (p *AzureBlobPath) Join(relativePath ...string) Path {
	args := []string{p.key}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Re-upload the blob with a correct base64-encoded MD5 (openssl dgst -md5 -binary file | openssl base64).
  2. Clear the blob's ContentMD5 property so Hash returns nil,nil instead of failing on invalid data.
  3. If the value is hex-encoded, convert it to base64 before comparing or patch the blob metadata.
  4. Set the ContentMD5 header explicitly at upload time so Azure validates and stores a proper base64 MD5.

Example fix

// before: hex md5 stored on blob -> "not valid MD5 sum: \"5d41402abc...\""
// after: set proper base64 md5 on upload
md5 := md5.Sum(data)
h.Header.Set("x-ms-blob-content-md5", base64.StdEncoding.EncodeToString(md5[:]))
Defensive patterns

Strategy: validation

Validate before calling

import (
    "encoding/base64"
    "encoding/hex"
)

// Validate/normalize a stored MD5 string before calling Hash
func validateMD5(s string) error {
    if s == "" { return nil }
    if b, err := base64.StdEncoding.DecodeString(s); err == nil && len(b) == 16 { return nil }
    if b, err := hex.DecodeString(s); err == nil && len(b) == 16 { return nil } // hex variant
    return fmt.Errorf("not a valid MD5: %q", s)
}

Type guard

func isValidBase64MD5(s string) bool {
    if s == "" { return true } // treated as no-hash
    b, err := base64.StdEncoding.DecodeString(s)
    return err == nil && len(b) == 16
}

Prevention

When it happens

Trigger: Reading a blob whose ContentMD5 property is corrupt, empty-but-set, or was written by a tool that stored a hex-encoded or non-base64 MD5 string; calling Hash (or PreferredHash) on such a VFSPath.

Common situations: Blobs uploaded by third-party tools (azcopy configs, terraform, custom scripts) that wrote hex MD5 instead of base64; blobs uploaded without MD5 computed then patched with a malformed value; older Azure tooling version differences in how ContentMD5 is set.

Related errors


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