hashicorp/terraform · error
invalid md5
Error message
invalid md5
What it means
Returned by RemoteClient.getMD5 (internal/backend/remote-state/s3/client.go:621) when the 'Digest' value read from the DynamoDB locking table fails to hex-decode or its decoded length is not md5.Size (16 bytes). The Digest attribute stores the MD5 of the last-written state for consistency checks; a malformed digest means integrity verification is impossible. Get() logs the error and, if the digest is non-empty and mismatches beyond the retry window, surfaces a badChecksumError.
Source
Thrown at internal/backend/remote-state/s3/client.go:621
TableName: aws.String(c.ddbTable),
ConsistentRead: aws.Bool(true),
}
resp, err := c.dynClient.GetItem(ctx, getParams)
if err != nil {
return nil, fmt.Errorf("Unable to retrieve item from DynamoDB table %q: %w", c.ddbTable, err)
}
var val string
if v, ok := resp.Item["Digest"]; ok {
if v, ok := v.(*dynamodbtypes.AttributeValueMemberS); ok {
val = v.Value
}
}
sum, err := hex.DecodeString(val)
if err != nil || len(sum) != md5.Size {
return nil, errors.New("invalid md5")
}
return sum, nil
}
// store the hash of the state so that clients can check for stale state files.
func (c *RemoteClient) putMD5(ctx context.Context, sum []byte) error {
if c.ddbTable == "" {
return nil
}
if len(sum) != md5.Size {
return errors.New("invalid payload md5")
}
putParams := &dynamodb.PutItemInput{
Item: map[string]dynamodbtypes.AttributeValue{
"LockID": &dynamodbtypes.AttributeValueMemberS{View on GitHub (pinned to c9def3e214)
Solutions
- Inspect the DynamoDB item and correct or delete the malformed Digest attribute (a 32-char lowercase hex MD5).
- Re-push a known-good state with 'terraform state push' to rewrite the digest.
- Confirm no external process is mutating the locking table.
Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the digest is well-formed before relying on it.
if d, err := hex.DecodeString(storedDigest); err != nil || len(d) != md5.Size {
log.Println("[WARN] DynamoDB Digest is malformed; state integrity check skipped")
} Try / catch
if _, err := client.getMD5(ctx); err != nil {
if strings.Contains(err.Error(), "invalid md5") {
log.Println("[ERROR] DynamoDB Digest corrupt; consider 'terraform state push' to repair")
}
} Prevention
- Do not manually edit the DynamoDB Digest attribute.
- After aborted applies, verify the Digest matches the S3 state via 'terraform state pull/push'.
- Restrict write access to the DynamoDB locking table to terraform only.
When it happens
Trigger: The DynamoDB item at LockID = <bucket>/<key>-md5 has a 'Digest' attribute that is not a 32-char hex string; external/manual edits to the table; a corrupt or partial write left a bad digest; the Digest column was overwritten with wrong data.
Common situations: Manual edits to the DynamoDB locking table; an aborted/crashed Put that wrote the S3 object but a malformed Digest; switching DynamoDB schema/format between versions; another tool writing to the same table with a different encoding.
Related errors
- invalid md5
- missing state name
- failed to store state MD5: %w
- failed to unlock both S3 and DynamoDB: S3 error: %v, DynamoD
- S3 bucket %q does not exist. The referenced S3 bucket must
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/f9b968d29348d949.
Report an issue: GitHub.