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.URL

View on GitHub (pinned to c9def3e214)

Solutions

  1. 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).
  2. Remove/strip the malformed Content-MD5 header at the proxy so the backend falls back to computing the MD5 from the body.
  3. 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

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

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/8672be54f9c41042. Report an issue: GitHub.