{"record":{"id":"7178c9e41f51ebf6","repo":"hashicorp/nomad","slug":"invalid-digest-format","errorCode":null,"errorMessage":"invalid digest format","messagePattern":"invalid digest format","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"api/ioutil.go","lineNumber":43,"sourceCode":"\n\t// checksum is the base64 component of checksum\n\tchecksum string\n\n\t// hash is the hashing function used to compute the checksum\n\thash hash.Hash\n}\n\n// newChecksumValidatingReader returns a checksum-validating wrapper reader, according\n// to a digest received in HTTP header\n//\n// The digest must be in the format \"<algo>=<base64 of hash>\" (e.g. \"sha-256=gPelGB7...\").\n//\n// When the reader is fully consumed (i.e. EOT is encountered), if the checksum don't match,\n// `Read` returns a checksum mismatch error.\nfunc newChecksumValidatingReader(r io.ReadCloser, digest string) (io.ReadCloser, error) {\n\tparts := strings.SplitN(digest, \"=\", 2)\n\tif len(parts) != 2 {\n\t\treturn nil, errors.New(\"invalid digest format\")\n\t}\n\n\talgo := parts[0]\n\tvar hash hash.Hash\n\tswitch algo {\n\tcase \"sha-256\":\n\t\thash = sha256.New()\n\tcase \"sha-512\":\n\t\thash = sha512.New()\n\tdefault:\n\t\treturn nil, errors.New(\"unsupported checksum format\")\n\t}\n\n\treturn &checksumValidatingReader{\n\t\tr:        r,\n\t\talgo:     algo,\n\t\tchecksum: parts[1],\n\t\thash:     hash,","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/hashicorp/nomad/blob/482b49bf1aec006f089bcfc7e632d8f6ac303e5e/api/ioutil.go#L25-L61","documentation":"Returned by newChecksumValidatingReader in api/ioutil.go when the digest string does not contain a '=' separator (checked with strings.SplitN(digest, \"=\", 2)). This library expects digests in 'algorithm=value' form (e.g. 'sha-256=abc123'); anything else is rejected before any hashing is set up.","triggerScenarios":"Calling Snapshot (or any API path that wires a checksum-validated body reader) with a Content-Digest header or digest argument that has no '=' character, e.g. a bare hex hash 'abc123...' or an empty string.","commonSituations":"A proxy or middleware strips or rewrites the Content-Digest header; the server sends a checksum in a non-standard format; a custom test harness passes a raw hash value instead of the RFC 3230 digest expression.","solutions":["Verify the digest string passed to newChecksumValidatingReader/Snapshot contains an '=' separator in 'algo=value' form","Log/inspect the raw digest header from the server; strip any quotes or whitespace mangling","Normalize the digest before passing it in, e.g. prefix with 'sha-256=' if only the hash is available","If the server uses an unsupported header form, compute the digest client-side instead"],"exampleFix":"// before\nr, err := newChecksumValidatingReader(resp.Body, resp.Header.Get(\"Digest\"))\n// after\ndigest := resp.Header.Get(\"Digest\")\nif !strings.Contains(digest, \"=\") {\n    digest = \"sha-256=\" + digest\n}\nr, err := newChecksumValidatingReader(resp.Body, digest)","handlingStrategy":"validation","validationCode":"func digestLooksValid(digest string) bool {\n    parts := strings.SplitN(digest, \"=\", 2)\n    return len(parts) == 2 && parts[0] != \"\" && parts[1] != \"\"\n}","typeGuard":null,"tryCatchPattern":"r, err := newChecksumValidatingReader(body, digest)\nif err != nil {\n    return fmt.Errorf(\"digest %q rejected: %w\", digest, err)\n}","preventionTips":["Always transmit digests as 'algo=value' per RFC 3230","Log the raw digest header when this error fires","Guard against proxies stripping/rewriting the Digest header","Unit-test the reader with malformed digests"],"tags":["go","checksum","input-validation","http"],"backgroundTag":"invalid-digest-format","analyzedSha":"482b49bf1aec006f089bcfc7e632d8f6ac303e5e","analyzedAt":"2026-09-04T07:54:14.808Z","contentChangedAt":"2026-09-04T07:54:14.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}