hashicorp/terraform · error
Failed to decode Content-MD5 '%s': %s
Error message
Failed to decode Content-MD5 '%s': %s
What it means
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.
Source
Thrown at internal/backend/remote-state/http/client.go:191
if _, err := io.Copy(buf, resp.Body); err != nil {
return nil, diags.Append(fmt.Errorf("Failed to read remote state: %s", err))
}
// Create the payload
payload := &remote.Payload{
Data: buf.Bytes(),
}
// If there was no data, then return nil
if len(payload.Data) == 0 {
return nil, diags
}
// Check for the MD5
if raw := resp.Header.Get("Content-MD5"); raw != "" {
md5, err := base64.StdEncoding.DecodeString(raw)
if err != nil {
return nil, diags.Append(fmt.Errorf(
"Failed to decode Content-MD5 '%s': %s", raw, err))
}
payload.MD5 = md5
} else {
// Generate the MD5
hash := md5.Sum(payload.Data)
payload.MD5 = hash[:]
}
return payload, diags
}
func (c *httpClient) Put(data []byte) tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
// Copy the target URL
base := *c.URLView on GitHub (pinned to c9def3e214)
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.
Example fix
# before - server emits hex MD5 Content-MD5: d41d8cd98f00b204e9800998ecf8427e # after - emit standard base64 of the raw 16-byte digest Content-MD5: 1B2M2Y8AsgTpgAmY7PhCfg== # or simply omit the header so the backend computes the MD5 itself
Defensive patterns
Strategy: validation
Validate before calling
# Verify the Content-MD5 header is valid standard base64 of 16 raw bytes before relying on it curl -sS -D - -o /dev/null -u "$USER:$PASS" "$STATE_URL" | grep -i content-md5 echo "<value>" | base64 -d | wc -c # should print 16
Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- The remote state does not match the expected hash
- Failed to read remote state: %s
- HTTP error: %d
- state data in OSS does not have the expected content. This
- failed to store state MD5: %s
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/8672be54f9c41042.
Report an issue: GitHub.