{"record":{"id":"8672be54f9c41042","repo":"hashicorp/terraform","slug":"failed-to-decode-content-md5-s-s","errorCode":null,"errorMessage":"Failed to decode Content-MD5 '%s': %s","messagePattern":"Failed to decode Content-MD5 '(.+?)': (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/http/client.go","lineNumber":191,"sourceCode":"\tif _, err := io.Copy(buf, resp.Body); err != nil {\n\t\treturn nil, diags.Append(fmt.Errorf(\"Failed to read remote state: %s\", err))\n\t}\n\n\t// Create the payload\n\tpayload := &remote.Payload{\n\t\tData: buf.Bytes(),\n\t}\n\n\t// If there was no data, then return nil\n\tif len(payload.Data) == 0 {\n\t\treturn nil, diags\n\t}\n\n\t// Check for the MD5\n\tif raw := resp.Header.Get(\"Content-MD5\"); raw != \"\" {\n\t\tmd5, err := base64.StdEncoding.DecodeString(raw)\n\t\tif err != nil {\n\t\t\treturn nil, diags.Append(fmt.Errorf(\n\t\t\t\t\"Failed to decode Content-MD5 '%s': %s\", raw, err))\n\t\t}\n\n\t\tpayload.MD5 = md5\n\t} else {\n\t\t// Generate the MD5\n\t\thash := md5.Sum(payload.Data)\n\t\tpayload.MD5 = hash[:]\n\t}\n\n\treturn payload, diags\n}\n\nfunc (c *httpClient) Put(data []byte) tfdiags.Diagnostics {\n\tvar diags tfdiags.Diagnostics\n\n\t// Copy the target URL\n\tbase := *c.URL","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/backend/remote-state/http/client.go#L173-L209","documentation":"The HTTP backend received a Content-MD5 response header that is not valid base64. After a successful 200 response, Get() base64-decodes the Content-MD5 header to verify integrity; if StdEncoding.DecodeString fails, this error is returned and the state is rejected before use.","triggerScenarios":"A GET response carries a `Content-MD5` header whose value is not valid standard base64 (e.g. hex-encoded, contains spaces/illegal chars, or is truncated), triggering the decode error at client.go:189-192.","commonSituations":"A custom state server or middleware that emits a hex-encoded MD5 or a base64url value instead of standard base64; a proxy rewriting/stripping header characters; a misconfigured S3-compatible gateway returning a malformed Content-MD5.","solutions":["Fix the state server to emit a standard base64-encoded raw MD5 in the Content-MD5 header, or omit the header entirely (the backend will compute the MD5 itself if absent).","Remove/strip the malformed Content-MD5 header at the proxy so the backend falls back to computing the MD5 from the body.","Verify the exact header value with curl -v against the state URL."],"exampleFix":"# before - server emits hex MD5\nContent-MD5: d41d8cd98f00b204e9800998ecf8427e\n\n# after - emit standard base64 of the raw 16-byte digest\nContent-MD5: 1B2M2Y8AsgTpgAmY7PhCfg==\n\n# or simply omit the header so the backend computes the MD5 itself","handlingStrategy":"validation","validationCode":"# Verify the Content-MD5 header is valid standard base64 of 16 raw bytes before relying on it\ncurl -sS -D - -o /dev/null -u \"$USER:$PASS\" \"$STATE_URL\" | grep -i content-md5\necho \"<value>\" | base64 -d | wc -c   # should print 16","typeGuard":null,"tryCatchPattern":null,"preventionTips":["If you control the server, omit Content-MD5 rather than emit a malformed one; the backend computes the MD5 itself when the header is absent.","Standardize on base64.StdEncoding of the raw 16-byte MD5 digest for any Content-MD5 header.","Do not run the MD5 through hex encoding or base64url."],"tags":["http","remote-state","md5","base64","header"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}