{"record":{"id":"890d28cacf81ac7c","repo":"hashicorp/terraform","slug":"unable-to-retrieve-item-from-dynamodb-table-q-w","errorCode":null,"errorMessage":"Unable to retrieve item from DynamoDB table %q: %w","messagePattern":"Unable to retrieve item from DynamoDB table %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/s3/client.go","lineNumber":609,"sourceCode":"func (c *RemoteClient) getMD5(ctx context.Context) ([]byte, error) {\n\tif c.ddbTable == \"\" {\n\t\treturn nil, nil\n\t}\n\n\tgetParams := &dynamodb.GetItemInput{\n\t\tKey: map[string]dynamodbtypes.AttributeValue{\n\t\t\t\"LockID\": &dynamodbtypes.AttributeValueMemberS{\n\t\t\t\tValue: c.lockPath() + stateIDSuffix,\n\t\t\t},\n\t\t},\n\t\tProjectionExpression: aws.String(\"LockID, Digest\"),\n\t\tTableName:            aws.String(c.ddbTable),\n\t\tConsistentRead:       aws.Bool(true),\n\t}\n\n\tresp, err := c.dynClient.GetItem(ctx, getParams)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"Unable to retrieve item from DynamoDB table %q: %w\", c.ddbTable, err)\n\t}\n\n\tvar val string\n\tif v, ok := resp.Item[\"Digest\"]; ok {\n\t\tif v, ok := v.(*dynamodbtypes.AttributeValueMemberS); ok {\n\t\t\tval = v.Value\n\t\t}\n\t}\n\n\tsum, err := hex.DecodeString(val)\n\tif err != nil || len(sum) != md5.Size {\n\t\treturn nil, errors.New(\"invalid md5\")\n\t}\n\n\treturn sum, nil\n}\n\n// store the hash of the state so that clients can check for stale state files.","sourceCodeStart":591,"sourceCodeEnd":627,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/backend/remote-state/s3/client.go#L591-L627","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: missing GetItem\n// after\n{\n  \"Effect\": \"Allow\",\n  \"Action\": [\"dynamodb:GetItem\", \"dynamodb:PutItem\", \"dynamodb:DeleteItem\"],\n  \"Resource\": \"arn:aws:dynamodb:*:*:table/terraform-locks\"\n}","handlingStrategy":"validation","validationCode":"// Confirm the digest row is readable before a write\nfunc preflightDigest(ctx context.Context, ddbs *dynamodb.Client, table, digestKey string) error {\n  if _, err := ddbs.DescribeTable(ctx, &dynamodb.DescribeTableInput{TableName: &table}); err != nil {\n    return err\n  }\n  _, err := ddbs.GetItem(ctx, &dynamodb.GetItemInput{\n    Key: map[string]types.AttributeValue{\"LockID\": &types.AttributeValueMemberS{Value: digestKey}},\n    ProjectionExpression: aws.String(\"LockID, Digest\"),\n    TableName: &table, ConsistentRead: aws.Bool(true),\n  })\n  return err\n}","typeGuard":null,"tryCatchPattern":"if _, err := client.getMD5(ctx); err != nil {\n    if strings.Contains(err.Error(), \"Unable to retrieve item from DynamoDB\") {\n        // verify table/IAM before retrying the plan/apply\n    }\n}","preventionTips":["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."],"tags":["dynamodb","terraform-state","iam","aws"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}