The Scenario
Running terraform import to bring an existing AWS resource under Terraform management. The command fails immediately with:
Error: Cannot import non-existent remote object
While attempting to import an existing object to aws_instance.example,
the provider detected that no object exists with the given id.
Only pre-existing objects can be imported.
The resource visually exists in the AWS console โ or at least, you think it does. This error means Terraform's provider looked up the ID you passed and came back empty.
Why This Happens
The import command itself is straightforward: Terraform calls the cloud API with the ID you gave it. If the API returns nothing, you get this error. The causes are almost always one of these:
- Wrong resource ID โ the most common cause. Each resource type has its own ID format, and mixing them up is easy.
- Wrong AWS region โ your provider is configured for
us-east-1but the resource lives inap-southeast-1. - Wrong AWS account โ the credentials in your shell point to a different account than where the resource was created.
- Resource was already deleted โ it existed when you started writing the import block but got cleaned up before you ran it.
- Wrong resource type โ trying to import an RDS cluster ID into
aws_db_instanceinstead ofaws_rds_cluster.
Quick Fix โ Diagnose Before Re-running
Step 1: Confirm the resource actually exists
Before touching Terraform, verify with the AWS CLI:
# For EC2 instance
aws ec2 describe-instances --instance-ids i-0abc123def456 --region us-east-1
# For S3 bucket
aws s3api head-bucket --bucket my-bucket-name
# For RDS instance
aws rds describe-db-instances --db-instance-identifier mydb --region us-east-1
If the CLI also returns nothing โ or an explicit not found error โ the resource is gone. Skip to the section below on handling deleted resources.
Step 2: Check which account and region your credentials use
aws sts get-caller-identity
aws configure get region
Compare the account ID and region against where the resource actually lives. If they don't match, either switch profiles or set the region explicitly:
export AWS_PROFILE=production
export AWS_DEFAULT_REGION=ap-southeast-1
terraform import aws_instance.example i-0abc123def456
Step 3: Verify the ID format for the resource type
Every resource type expects a specific ID format. A few that frequently catch people:
# EC2 instance โ use the instance ID directly
terraform import aws_instance.web i-0abc123def456
# Security group โ use the sg- ID
terraform import aws_security_group.main sg-0abc123def456
# IAM role โ use the role NAME, not ARN
terraform import aws_iam_role.deployer my-deployer-role
# S3 bucket โ use the bucket name
terraform import aws_s3_bucket.assets my-assets-bucket
# RDS cluster (not aws_db_instance!)
terraform import aws_rds_cluster.main my-cluster-id
# Subnet โ use subnet ID
terraform import aws_subnet.private subnet-0abc123def456
The Terraform registry documentation for each resource always lists the import ID format at the bottom of the page under the Import section. Check it before running.
Step 4: Re-run with verbose output
If you're still unsure what's happening, run with logging enabled to see exactly what API call the provider is making:
TF_LOG=DEBUG terraform import aws_instance.example i-0abc123def456 2>&1 | grep -i "describe\|import\|error"
The debug output will show the exact API call and response, which makes the mismatch obvious.
Handling a Deleted Resource
If the resource genuinely no longer exists, you have two paths:
Option A โ Remove the import block (Terraform 1.5+ import blocks)
If you're using the newer HCL-based import syntax, just delete the block and the associated resource config:
# Remove this from your .tf file:
import {
to = aws_instance.example
id = "i-0abc123def456"
}
resource "aws_instance" "example" {
# ...
}
Option B โ Remove state entry if it was partially imported
Sometimes the state gets into a weird half-imported state. Clean it up:
# Check if it's in state
terraform state list | grep example
# Remove if it snuck in
terraform state rm aws_instance.example
Option C โ Let Terraform create it fresh
If you removed the import block but kept the resource block, terraform plan will now show it as a new resource to create. That's usually the right outcome when the original is gone.
Permanent Fix โ Verify Before You Import
The cleanest workflow before any import operation:
#!/bin/bash
# verify-before-import.sh
RESOURCE_ID="$1"
REGION="${2:-us-east-1}"
echo "Checking instance $RESOURCE_ID in $REGION..."
aws ec2 describe-instances \
--instance-ids "$RESOURCE_ID" \
--region "$REGION" \
--query 'Reservations[0].Instances[0].State.Name' \
--output text
if [ $? -ne 0 ]; then
echo "Resource not found โ do not run terraform import"
exit 1
fi
echo "Resource exists. Safe to import."
Run this before every import and you'll never hit this error from a deleted or non-existent resource again.
Verification โ Confirming the Fix Worked
After correcting the ID or region and re-running import:
# 1. Import should complete without error
terraform import aws_instance.example i-0abc123def456
# Expected: Import successful!
# 2. Check state was populated
terraform state show aws_instance.example
# Should show the full resource attributes
# 3. Run plan โ ideally shows no changes
terraform plan
# Expected: No changes. Your infrastructure matches the configuration.
If terraform plan still shows changes after import, it means the resource config in your .tf file doesn't match the actual resource. That's a separate drift issue โ but the import error itself is resolved.

