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

  1. Confirm dynamodb:GetItem is allowed on the table ARN for the running principal.
  2. Verify the dynamodb_table name and region in the backend block.
  3. If on provisioned capacity, scale read units or switch to on-demand.
  4. 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

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


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