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
- Re-upload the blob with a correct base64-encoded MD5 (openssl dgst -md5 -binary file | openssl base64).
- Clear the blob's ContentMD5 property so Hash returns nil,nil instead of failing on invalid data.
- If the value is hex-encoded, convert it to base64 before comparing or patch the blob metadata.
- 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
- Always set x-ms-blob-content-md5 (base64) when uploading blobs to Azure
- Never store hex-encoded MD5 in blob ContentMD5 properties
- Scan existing buckets for blobs with malformed ContentMD5 and clear or re-upload them
- Use PreferredHash/verify flow that tolerates nil hashes when MD5 is absent
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
- decoding PKCS7 signature: %w
- failed to decode user data: %w
- DNS not implemented on azureCloud
- FindVPCInfo not implemented on azureCloud, use FindVNetInfo
- DeleteGroup not implemented on azureCloud
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/79d219f515130595.
Report an issue: GitHub.