{"record":{"id":"f9df1b9c59b83112","repo":"kubernetes/kops","slug":"unable-to-parse-sha-q-v","errorCode":null,"errorMessage":"unable to parse sha: %q, %v","messagePattern":"unable to parse sha: %q, (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/assets/assetcopy/copyfile.go","lineNumber":140,"sourceCode":"\tuploadVFS, err := vfsContext.BuildVfsPath(objectStore)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error building path %q: %v\", objectStore, err)\n\t}\n\n\tshaExtension, err := fileExtensionForSHA(sha)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tshaTarget := objectStore + shaExtension\n\tshaVFS, err := vfsContext.BuildVfsPath(shaTarget)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error building path %q: %v\", shaTarget, err)\n\t}\n\n\tshaHash, err := hashing.FromString(strings.TrimSpace(sha))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to parse sha: %q, %v\", sha, err)\n\t}\n\n\tin := bytes.NewReader(data)\n\tdataHash, err := shaHash.Algorithm.Hash(in)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to hash file %q downloaded: %v\", source, err)\n\t}\n\n\tif !shaHash.Equal(dataHash) {\n\t\treturn fmt.Errorf(\"the sha value in %q does not match %q calculated value %q\", shaTarget, source, dataHash.String())\n\t}\n\n\tklog.Infof(\"uploading %q to %q\", source, objectStore)\n\tif err := writeFile(ctx, cluster, uploadVFS, data); err != nil {\n\t\treturn err\n\t}\n\n\tb := []byte(shaHash.Hex())","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/assets/assetcopy/copyfile.go#L122-L158","documentation":"The expected sha string is parsed via hashing.FromString(strings.TrimSpace(sha)); if the hash string cannot be parsed into a known hashing object (e.g. it is not valid hex of length 40/64, or an unrecognized algorithm prefix), the task fails with 'unable to parse sha: <sha>, <reason>'.","triggerScenarios":"FileAsset.SHAValue contains characters that are not valid hex, or a hash in a format hashing.FromString does not recognize (lengths already validated as 40/64 by fileExtensionForSHA, so this catches non-hex garbage of those lengths).","commonSituations":"A hand-edited checksum file or asset spec with placeholder text ('<sha256>') padded/truncated to pass length checks; a corrupted checksum fetched from a broken mirror.","solutions":["Inspect the sha printed in the error for non-hex characters.","Regenerate the correct sha1/sha256 of the source file (shasum / openssl dgst).","Fix the source checksum file or the cluster spec's sha value.","Re-run `kops get assets --copy`."],"exampleFix":"// before\nzzzz6c35c94fcfb415dbe95f408b9ce91ee846ed  file.tar.gz   # not hex\n// after\n2aae6c35c94fcfb415dbe95f408b9ce91ee846ed  file.tar.gz","handlingStrategy":"validation","validationCode":"sha := strings.TrimSpace(expectedSHA)\nif _, err := hex.DecodeString(sha); err != nil {\n    return fmt.Errorf(\"sha must be hex: %v\", err)\n}\nif len(sha) != 40 && len(sha) != 64 {\n    return fmt.Errorf(\"sha must be 40 or 64 hex chars, got %d\", len(sha))\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Regenerate checksums with shasum/openssl instead of hand-editing","Validate checksum files (hex, correct length) before publishing to mirrors","Never placeholder-fill sha fields in generated specs","Cross-check a published sha against the actual file once before bulk copy"],"tags":["go","sha","parsing","asset-copy"],"backgroundTag":"invalid-checksum-format","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}