hashicorp/terraform · error
Unable to retrieve item from DynamoDB table %q: %w
Error message
Unable to retrieve item from DynamoDB table %q: %w
What it means
Thrown by getMD5 when the DynamoDB GetItem for the state checksum (LockID = lockPath()+stateIDSuffix, attributes LockID+Digest) returns an error. getMD5 is used to detect stale local state by comparing the stored MD5 digest before a remote write.
Source
Thrown at internal/backend/remote-state/s3/client.go:609
func (c *RemoteClient) getMD5(ctx context.Context) ([]byte, error) {
if c.ddbTable == "" {
return nil, nil
}
getParams := &dynamodb.GetItemInput{
Key: map[string]dynamodbtypes.AttributeValue{
"LockID": &dynamodbtypes.AttributeValueMemberS{
Value: c.lockPath() + stateIDSuffix,
},
},
ProjectionExpression: aws.String("LockID, Digest"),
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.View on GitHub (pinned to c9def3e214)
Solutions
- Confirm dynamodb:GetItem is allowed on the table ARN for the running principal.
- Verify the dynamodb_table name and region in the backend block.
- If on provisioned capacity, scale read units or switch to on-demand.
- If the table was intentionally removed, remove dynamodb_table from the backend config.
Example fix
// before: missing GetItem
// after
{
"Effect": "Allow",
"Action": ["dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:DeleteItem"],
"Resource": "arn:aws:dynamodb:*:*:table/terraform-locks"
} Defensive patterns
Strategy: validation
Validate before calling
// Confirm the digest row is readable before a write
func preflightDigest(ctx context.Context, ddbs *dynamodb.Client, table, digestKey string) error {
if _, err := ddbs.DescribeTable(ctx, &dynamodb.DescribeTableInput{TableName: &table}); err != nil {
return err
}
_, err := ddbs.GetItem(ctx, &dynamodb.GetItemInput{
Key: map[string]types.AttributeValue{"LockID": &types.AttributeValueMemberS{Value: digestKey}},
ProjectionExpression: aws.String("LockID, Digest"),
TableName: &table, ConsistentRead: aws.Bool(true),
})
return err
} Try / catch
if _, err := client.getMD5(ctx); err != nil {
if strings.Contains(err.Error(), "Unable to retrieve item from DynamoDB") {
// verify table/IAM before retrying the plan/apply
}
} Prevention
- Run a DescribeTable pre-flight before plan/apply.
- Grant dynamodb:GetItem on the lock table.
- Match the table region to the S3 bucket region.
- Size provisioned capacity to CI concurrency.
When it happens
Trigger: A read/refresh/write operation triggers getMD5 -> c.dynClient.GetItem fails on the digest row: table missing, AccessDenied on dynamodb:GetItem, throttling, or a regional endpoint mismatch.
Common situations: Backend configured with a dynamodb_table that no longer exists; IAM policy missing dynamodb:GetItem; table in a different region than configured; provisioned capacity exhausted under concurrency.
Related errors
- failed to unlock both S3 and DynamoDB: S3 error: %v, DynamoD
- failed to unlock DynamoDB: %v
- failed to retrieve lock info for lock ID %q: %s
- Unable to delete item from DynamoDB table %q: %w
- failed to unlock S3: %v
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/890d28cacf81ac7c.
Report an issue: GitHub.