Quick Answer
# Check what's currently in state
terraform state show aws_instance.web
# If it's the wrong resource, remove and reimport
terraform state rm aws_instance.web
terraform import aws_instance.web i-0correct123
The Error
Error: Resource already managed by Terraform
Terraform is already managing a remote object for
aws_instance.web. To import to this address you must
first remove the existing object from the Terraform state.
What Causes This
- Resource already imported — you’re importing something that’s already in state
- Wrong resource ID — the state has the old ID, you want to point to a new one
- State and infrastructure diverged — resource was replaced outside Terraform
- Duplicate import — running import twice on the same address
Solution 1: Check What’s Already in State
# See the current resource details
terraform state show aws_instance.web
# aws_instance.web:
resource "aws_instance" "web" {
ami = "ami-0abc123"
id = "i-0old456"
instance_type = "t3.micro"
...
}
If the state already has the correct resource, you don’t need to import — just run:
terraform plan # Should show no changes
Solution 2: Remove Old State, Import New Resource
If the state points to a wrong or deleted resource:
# 1. Remove the stale state entry
terraform state rm aws_instance.web
# 2. Import the correct resource
terraform import aws_instance.web i-0correct789
# 3. Verify
terraform plan
Solution 3: Use Import Blocks (Terraform 1.5+)
Instead of the CLI terraform import command, use declarative import blocks:
import {
to = aws_instance.web
id = "i-0correct789"
}
terraform plan # Shows the import plan
terraform apply # Performs the import
Import blocks handle the “already exists” check more gracefully and can be code-reviewed.
Generate Config from Import
# Auto-generate the resource config from existing infrastructure
terraform plan -generate-config-out=generated.tf
This creates a .tf file with the resource configuration matching the imported resource.
Solution 4: Bulk Import with Import Blocks
# Import multiple resources at once
import {
to = aws_instance.web
id = "i-0abc123"
}
import {
to = aws_security_group.web
id = "sg-0def456"
}
import {
to = aws_subnet.public[0]
id = "subnet-0ghi789"
}
terraform plan # Review all imports
terraform apply # Apply all at once
Remove the import blocks after successful import — they’re one-time use.
Solution 5: Handle for_each/count Resources
# Import into count-based resource
terraform import 'aws_instance.web[0]' i-0abc123
terraform import 'aws_instance.web[1]' i-0def456
# Import into for_each resource
terraform import 'aws_instance.web["primary"]' i-0abc123
terraform import 'aws_instance.web["secondary"]' i-0def456
# Import into module resource
terraform import 'module.vpc.aws_vpc.main' vpc-0abc123
Common Scenarios
Scenario: Migrating Existing Infrastructure to Terraform
# 1. Write the resource config in .tf files
# 2. Import each resource
terraform import aws_vpc.main vpc-0abc123
terraform import aws_subnet.public subnet-0def456
terraform import aws_security_group.web sg-0ghi789
# 3. Plan to see what differs
terraform plan
# 4. Adjust .tf files until plan shows no changes
Scenario: Renaming a Resource
# Renamed: aws_instance.web → aws_instance.app
# Option 1: state mv (no destroy/create)
terraform state mv aws_instance.web aws_instance.app
# Option 2: moved block (Terraform 1.1+)
moved {
from = aws_instance.web
to = aws_instance.app
}
state mv and moved blocks are better than remove+import because they don’t risk any infrastructure changes.
Hands-On Courses
- Terraform for Beginners on CopyPasteLearn
- Terraform By Example — practical code examples
Conclusion
“Already managed” means the resource address is taken in state. Check with terraform state show first — you may not need to import at all. If you need to reimport, use terraform state rm then terraform import. For new projects, prefer import blocks (Terraform 1.5+) and moved blocks for renames.