opentofu/opentofu · error
Failed to decode Content-MD5 '%s': %w
Error message
Failed to decode Content-MD5 '%s': %w
What it means
The state response carried a Content-MD5 header that is not valid base64, so the client cannot decode it for integrity checking, and it refuses the payload. Per RFC 1864 the header must be the base64 encoding of the raw 16-byte MD5 digest; sending hex text or any non-base64 value triggers this. The offending header value is included in the message.
Source
Thrown at internal/backend/remote-state/http/client.go:230
if _, err := io.Copy(buf, resp.Body); err != nil {
return nil, fmt.Errorf("Failed to read remote state: %w", 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, nil
}
// Check for the MD5
if raw := resp.Header.Get("Content-MD5"); raw != "" {
md5, err := base64.StdEncoding.DecodeString(raw)
if err != nil {
return nil, fmt.Errorf(
"Failed to decode Content-MD5 '%s': %w", raw, err)
}
payload.MD5 = md5
} else {
// Generate the MD5
hash := md5.Sum(payload.Data)
payload.MD5 = hash[:]
}
return payload, nil
}
func (c *httpClient) Put(ctx context.Context, data []byte) error {
// Copy the target URL
base := *c.URL
if c.lockID != "" {View on GitHub (pinned to 3561785c48)
Solutions
- Fix the server: send base64.StdEncoding.EncodeToString(md5.Sum(data)) in Go, or the equivalent in the server's language
- Alternatively omit the Content-MD5 response header entirely — the client then computes the MD5 locally
- Verify what is actually sent: curl -I "$ADDRESS" and try 'echo <value> | base64 -d' to confirm decodability
Example fix
// state server (Go), before
w.Header().Set("Content-MD5", hex.EncodeToString(md5bytes))
// after
w.Header().Set("Content-MD5", base64.StdEncoding.EncodeToString(md5bytes)) Defensive patterns
Strategy: validation
Validate before calling
# Pre-flight: confirm the server's Content-MD5 decodes as base64
val=$(curl -sI "$ADDRESS" | awk -F': ' 'tolower($1)=="content-md5" {print $2}' | tr -d '\r')
if [ -n "$val" ] && ! echo "$val" | base64 -d >/dev/null 2>&1; then
echo "Content-MD5 is not valid base64: $val"; exit 1
fi Prevention
- On the server, send base64(raw 16-byte MD5 digest) per RFC 1864, or omit the header entirely
- Add a response-header conformance test to the state server's CI
- Watch for proxies that rewrite content headers
When it happens
Trigger: A hand-rolled state server that hex-encodes the MD5 (32 hex chars) instead of base64-encoding the raw digest; an intermediary rewriting or corrupting the header; wrong padding/charset in a custom header injection.
Common situations: Custom state servers written without an RFC 1864-compliant MD5 helper; debug proxies adding their own Content-MD5; header rewritten by CDN transforms.
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
- error decoding client certificate: %w
- CPK: failed to decode base64 key %w
- Error decoding encryption key: %w
- auth object for %q in %s does not have base64-encoded userna
- the cached package for %s %s (in %s) does not match any of t
AI-assisted analysis of opentofu/opentofu@3561785c48 (2026-08-15).
Data as JSON: /api/errors/cdf50fce14aa9541.
Report an issue: GitHub.