Fix Terraform Error: CloudWatch Log Group Already Exists
Fix terraform CloudWatch Log Group ResourceAlreadyExistsException. Import orphaned log groups, prevent Lambda auto-creation
DevOps
Fix AWS AddressLimitExceeded when creating Elastic IPs in Terraform. Release unused EIPs, request quota increase, audit per-region usage
# Find unused EIPs and release them
aws ec2 describe-addresses --query 'Addresses[?AssociationId==`null`].[AllocationId,PublicIp]' --output table
# Release an unused EIP
aws ec2 release-address --allocation-id eipalloc-0abc1234Error: creating EC2 EIP: AddressLimitExceeded: The maximum number of addresses has been reached.
status code: 400
Error: creating NAT Gateway: AddressLimitExceeded: The maximum number of addresses has been reached.AWS limits Elastic IPs to 5 per region by default. Every NAT Gateway, bastion host, and public-facing instance with a static IP consumes one.
Common EIP consumers:
# List ALL EIPs in the region with association status
aws ec2 describe-addresses \
--query 'Addresses[].{IP:PublicIp,AllocID:AllocationId,AssocID:AssociationId,Instance:InstanceId}' \
--output table-------------------------------------------------------------------
| DescribeAddresses |
+------------------+------------------+--------+------------------+
| AllocID | AssocID | IP | Instance |
+------------------+------------------+--------+------------------+
| eipalloc-aaa111 | eipassoc-bbb222 | 1.2.3.4| i-0abc123 |
| eipalloc-ccc333 | None | 5.6.7.8| None | ← Unused
| eipalloc-ddd444 | None | 9.0.1.2| None | ← Unused
+------------------+------------------+--------+------------------+Release the unused ones:
# Release unused EIPs
aws ec2 release-address --allocation-id eipalloc-ccc333
aws ec2 release-address --allocation-id eipalloc-ddd444Or release ALL unused EIPs:
aws ec2 describe-addresses \
--query 'Addresses[?AssociationId==null].AllocationId' \
--output text | xargs -n1 aws ec2 release-address --allocation-id# Check current EIP quota
aws service-quotas get-service-quota \
--service-code ec2 \
--quota-code L-0263D0A3
# Request increase to 20
aws service-quotas request-service-quota-increase \
--service-code ec2 \
--quota-code L-0263D0A3 \
--desired-value 20Or through the AWS Console: Service Quotas → EC2 → Elastic IP addresses → Request increase
Typical approval: 1-3 business days for moderate increases.
# Instead of 3 NAT Gateways (3 EIPs):
resource "aws_nat_gateway" "single" {
allocation_id = aws_eip.nat.id
subnet_id = aws_subnet.public[0].id
}
resource "aws_eip" "nat" {
domain = "vpc"
}
# Route all private subnets through one NAT
resource "aws_route" "private" {
count = length(aws_subnet.private)
route_table_id = aws_route_table.private[count.index].id
destination_cidr_block = "0.0.0.0/0"
nat_gateway_id = aws_nat_gateway.single.id
}One NAT Gateway instead of three saves 2 EIPs + ~$65/month.
# Instead of EIP per instance, put them behind an ALB
resource "aws_lb" "web" {
name = "web-alb"
load_balancer_type = "application"
subnets = aws_subnet.public[*].id
}
# Instances in private subnets — no EIPs needed
resource "aws_instance" "web" {
count = 3
subnet_id = aws_subnet.private[count.index % length(aws_subnet.private)].id
# No EIP needed
}# No bastion host needed — connect via SSM Session Manager
resource "aws_iam_instance_profile" "ssm" {
role = aws_iam_role.ssm.name
}
resource "aws_instance" "web" {
iam_instance_profile = aws_iam_instance_profile.ssm.name
# No EIP, no public subnet needed
}aws ssm start-session --target i-0abc123# Check all regions
for region in us-east-1 us-west-2 eu-west-1 ap-southeast-1; do
count=$(aws ec2 describe-addresses --region $region --query 'length(Addresses)')
echo "$region: $count EIPs"
doneTrack EIPs to prevent orphaning:
resource "aws_eip" "nat" {
count = var.az_count
domain = "vpc"
tags = {
Name = "nat-${count.index}"
}
lifecycle {
# Prevent accidental EIP release (keeps your static IP)
prevent_destroy = true
}
}AWS limits Elastic IPs to 5 per region. Release unused EIPs first (aws ec2 describe-addresses to find them), then reduce consumption: use a single NAT Gateway for non-production, ALB instead of per-instance EIPs, and SSM instead of bastion hosts. Request a quota increase if you genuinely need more.
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.