Fix Terraform Error: CloudWatch Log Group Already Exists
Fix terraform CloudWatch Log Group ResourceAlreadyExistsException. Import orphaned log groups, prevent Lambda auto-creation
DevOps
Fix terraform prevent_destroy errors blocking resource deletion. Temporarily disable, use state rm to decouple
# Temporarily set to false
lifecycle {
prevent_destroy = false # Was true
}terraform apply # Applies the lifecycle change
terraform destroy -target=aws_db_instance.mainThen re-enable prevent_destroy = true.
Error: Instance cannot be destroyed
on rds.tf line 5:
5: resource "aws_db_instance" "main" {
Resource aws_db_instance.main has lifecycle.prevent_destroy set, but the
plan calls for this resource to be destroyed. To avoid this error and
continue with the plan, either disable lifecycle.prevent_destroy or
reduce the scope of the change.prevent_destroy = true in the lifecycle block intentionally blocks any operation that would destroy the resource. This triggers when:
terraform destroy — directly deleting protected resourcesengine forces replacement (destroy + create).tf filesaws_instance.web → aws_instance.app without moved blockresource "aws_db_instance" "main" {
# ...
lifecycle {
prevent_destroy = false # Temporarily disabled
}
}terraform apply # Apply the lifecycle change
terraform destroy -target=aws_db_instance.main # Now worksRemember to re-enable prevent_destroy = true for other environments!
If you want to stop managing the resource without destroying it:
# Removes from Terraform state — the actual resource stays in AWS
terraform state rm aws_db_instance.mainThen remove the resource block from your .tf files. The database continues running, just no longer managed by Terraform.
# This causes destroy + create (blocked by prevent_destroy)
# resource "aws_instance" "app" { ... } # renamed from "web"
# Instead, use moved block (no destroy):
moved {
from = aws_instance.web
to = aws_instance.app
}
resource "aws_instance" "app" {
# ...
lifecycle {
prevent_destroy = true
}
}If a force-replacement attribute triggers the error:
# ❌ This forces replacement (destroy + create) → blocked
resource "aws_db_instance" "main" {
engine = "mysql" # Was "postgres" — can't change in-place
lifecycle { prevent_destroy = true }
}
# ✅ Create new instance with different name, migrate data, then remove old
resource "aws_db_instance" "main_v2" {
engine = "mysql"
}Use it on resources where accidental deletion is catastrophic:
# Databases — data loss
resource "aws_db_instance" "production" {
lifecycle { prevent_destroy = true }
}
resource "aws_rds_cluster" "production" {
lifecycle { prevent_destroy = true }
}
# S3 buckets with important data
resource "aws_s3_bucket" "backups" {
lifecycle { prevent_destroy = true }
}
# DNS zones
resource "aws_route53_zone" "primary" {
lifecycle { prevent_destroy = true }
}
# KMS keys (can't be recreated with same ID)
resource "aws_kms_key" "main" {
lifecycle { prevent_destroy = true }
}Don't use it on:
resource "aws_db_instance" "main" {
deletion_protection = true # AWS-level protection
lifecycle {
prevent_destroy = true # Terraform-level protection
}
}Double protection: Terraform won't plan the destroy, AND AWS won't execute it even if Terraform tried.
prevent_destroy = true is working as intended — it's protecting your resource. Temporarily set it to false to destroy, use terraform state rm to decouple without destroying, or use moved blocks for renames. Apply it to databases, S3 buckets, and DNS zones — anything where data loss would be catastrophic.
Fix terraform CloudWatch Log Group ResourceAlreadyExistsException. Import orphaned log groups, prevent Lambda auto-creation
Fix terraform import errors when a resource already exists in state. Covers state rm, state show, reimport workflow, import blocks
Fix terraform too many command line arguments errors. Correct -var syntax, quote values with spaces, and learn proper Terraform CLI argument format for plan
Fix terraform invalid escape sequence errors. Double backslashes for Windows paths, use heredocs for regex, and learn all valid HCL escape sequences.