TerraformPilot

Troubleshooting

Fix Terraform Secrets Manager Secret - ResourceExistsException

Fix AWS Secrets Manager duplicate secret errors in Terraform. Handle secret recovery windows, force deletion, naming conventions, and secret restoration.

LLuca Berton1 min read

Quick Answer

#

A secret with the same name already exists, or was recently deleted and is in its recovery window (7-30 days by default). Import the existing secret, force-delete the old one with recovery_window_in_days = 0, or use a different name.

The Error

#
Error: creating Secrets Manager Secret (myapp/db-password):
  ResourceExistsException: The operation failed because the secret
  myapp/db-password already exists.

What Causes This Error

#
  1. Secret already exists — created manually or by another workspace
  2. Soft-deleted secret — Secrets Manager holds deleted secrets for 7-30 days (recovery window)
  3. Previous failed apply — secret created but not recorded in state

How to Fix It

#

Solution 1: Import the Existing Secret

#
# Check if secret exists
aws secretsmanager describe-secret --secret-id myapp/db-password
 
# Import using the secret ARN or name
terraform import aws_secretsmanager_secret.db_password myapp/db-password

Solution 2: Force Delete a Soft-Deleted Secret

#
# Check if the secret is scheduled for deletion
aws secretsmanager describe-secret --secret-id myapp/db-password \
  --query '{Name:Name,DeletedDate:DeletedDate}'
 
# Force immediate deletion (no recovery)
aws secretsmanager delete-secret \
  --secret-id myapp/db-password \
  --force-delete-without-recovery
 
# Wait a moment, then apply
sleep 5
terraform apply

Solution 3: Restore the Deleted Secret

#
# If the secret was accidentally deleted, restore it
aws secretsmanager restore-secret --secret-id myapp/db-password
 
# Then import into Terraform
terraform import aws_secretsmanager_secret.db_password myapp/db-password

Solution 4: Use recovery_window_in_days = 0 in Terraform

#
resource "aws_secretsmanager_secret" "db_password" {
  name                    = "${var.project}/${var.environment}/db-password"
  recovery_window_in_days = 0  # Immediate deletion — no recovery window
 
  tags = {
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}
 
resource "aws_secretsmanager_secret_version" "db_password" {
  secret_id     = aws_secretsmanager_secret.db_password.id
  secret_string = random_password.db.result
}

Solution 5: Use Unique Naming with Paths

#
resource "aws_secretsmanager_secret" "db_password" {
  name = "${var.project}/${var.environment}/${var.region}/db-password"
  # e.g., myapp/prod/us-east-1/db-password
}

Troubleshooting Checklist

#
  1. ✅ Does the secret exist? (aws secretsmanager describe-secret)
  2. ✅ Is it in a deletion recovery window?
  3. ✅ Should you import, restore, or force-delete it?
  4. ✅ Are you using unique path-based names?

Prevention Tips

#
  • Use path-based secret namesproject/env/secret-name prevents collisions
  • Set recovery_window_in_days = 0 for dev/test environments
  • Keep default recovery window (7 days) for production — protects against accidents
  • Import existing secrets before recreating
  • Tag secrets with ManagedBy = "terraform" for easy identification
#

Conclusion

#

Secrets Manager holds deleted secrets during a recovery window, blocking creation of new secrets with the same name. Force-delete with --force-delete-without-recovery for dev environments, or import existing secrets into Terraform. Use path-based naming conventions to avoid collisions.

#Terraform#AWS#Troubleshooting#Error Fix

Share this article