The DynamoDB ResourceInUseException error occurs when Terraform attempts to create a table that already exists or is in a transitional state. This happens when a table with the same name already exists in your AWS account, or the table is currently being modified. Most cases are resolved by importing the existing table into Terraform state or using a different table name.
AWS DynamoDB returns a ResourceInUseException when an operation conflicts with an existing resource. When creating a table, this means either: (1) a table with the same name already exists in your AWS account, (2) the table is currently in a transitional state (being created, deleted, or modified), or (3) there's a race condition where multiple Terraform operations are trying to modify the same resource simultaneously. Terraform cannot proceed with table creation until the conflict is resolved.
First, confirm whether the DynamoDB table actually exists in your AWS account:
aws dynamodb list-tables --region us-east-1Or use the AWS Console: Go to DynamoDB > Tables and check if a table with your configured name exists. If it exists, move to step 2. If it doesn't exist, move to step 4.
If the table exists but isn't managed by Terraform, import it into your Terraform state:
terraform import aws_dynamodb_table.my_table my-table-nameReplace my_table with your resource name in Terraform and my-table-name with the actual table name in AWS. This tells Terraform to manage the existing resource instead of creating a new one.
After importing, run:
terraform planVerify the plan shows no changes. If it does, your Terraform configuration may not match the existing table—update your configuration accordingly.
After importing, ensure your Terraform configuration exactly matches the existing table's configuration:
resource "aws_dynamodb_table" "my_table" {
name = "my-table-name"
billing_mode = "PAY_PER_REQUEST" # Or PROVISIONED
hash_key = "id"
range_key = "sort_key" # If applicable
attribute {
name = "id"
type = "S"
}
ttl {
attribute_name = "TTL" # If TTL is enabled
enabled = true
}
}Compare with your actual table configuration in the AWS Console. Update your Terraform code to match exactly, then run terraform plan again to ensure no changes are needed.
If the table is in a transitional state (e.g., updating a Global Secondary Index), wait for the operation to complete before running Terraform again:
aws dynamodb describe-table --table-name my-table-name --region us-east-1Check the "TableStatus" field. It should be "ACTIVE" before Terraform can modify it. Common transitional states include:
- CREATING: Table is being created
- UPDATING: GSI or capacity is being modified
- DELETING: Table is being deleted
Wait for the operation to complete (check every 30 seconds), then retry:
terraform applyIf you don't want to manage the existing table with Terraform, create a new table with a different name:
resource "aws_dynamodb_table" "my_table" {
name = "my-table-name-v2" # Changed name
billing_mode = "PAY_PER_REQUEST"
hash_key = "id"
attribute {
name = "id"
type = "S"
}
}Then run:
terraform applyIf the old table is no longer needed, delete it manually through the AWS Console.
If you're experiencing race conditions (multiple resources trying to modify the same table), ensure proper resource ordering with depends_on:
resource "aws_dynamodb_table" "my_table" {
name = "my-table-name"
billing_mode = "PAY_PER_REQUEST"
hash_key = "id"
attribute {
name = "id"
type = "S"
}
}
resource "aws_dynamodb_global_secondary_index" "my_gsi" {
table_name = aws_dynamodb_table.my_table.name
index_name = "gsi-index"
hash_key = "gsi_key"
projection_type = "ALL"
write_capacity_units = 10
read_capacity_units = 10
depends_on = [aws_dynamodb_table.my_table]
}Alternatively, define GSI within the table resource to avoid race conditions:
resource "aws_dynamodb_table" "my_table" {
name = "my-table-name"
billing_mode = "PROVISIONED"
hash_key = "id"
read_capacity = 10
write_capacity = 10
attribute {
name = "id"
type = "S"
}
global_secondary_index {
name = "gsi-index"
hash_key = "gsi_key"
projection_type = "ALL"
read_capacity = 10
write_capacity = 10
}
}If Terraform state is severely out of sync with AWS, refresh the state:
terraform refreshThis updates the Terraform state file to reflect the current AWS infrastructure. Then review the changes:
terraform planIf the plan shows deletions or unexpected changes, carefully review before applying:
terraform applyLocalStack Testing: When using LocalStack (local DynamoDB emulator) for testing, ResourceInUseException can occur immediately after starting LocalStack. Wait a few seconds after startup before creating tables, or add retry logic in your infrastructure code.
Terraform State Recovery: If a table was created but Terraform crashed before updating the state file, the table exists in AWS but not in your .tfstate file. The terraform import command is the safest way to recover. Never manually edit .tfstate files.
Billing Mode Mismatches: Ensure your Terraform configuration specifies the correct billing mode (PROVISIONED or PAY_PER_REQUEST). Changing billing modes requires table updates, which can conflict with concurrent operations.
Regional Considerations: DynamoDB tables are region-specific. Ensure your Terraform provider is configured for the correct region and that you're checking the table in the right region.
Global Tables: If using DynamoDB Global Tables, ResourceInUseException can occur during replication across regions. Wait for replication to complete before modifying the table.
Error: Error installing helm release: cannot re-use a name that is still in use
How to fix "release name in use" error in Terraform with Helm
Error: Error creating GKE Cluster: BadRequest
BadRequest error creating GKE cluster in Terraform
Error: External program failed to produce valid JSON
External program failed to produce valid JSON
Error: Unsupported argument in child module call
How to fix "Unsupported argument in child module call" in Terraform
Error: network is unreachable
How to fix "network is unreachable" in Terraform