Skip to main content
Fix Terraform Error: Instance Not Found After External Deletion

Fix Terraform Error: Instance Not Found After External Deletion

Key Takeaway

Fix terraform instance not found errors when resources are deleted outside of Terraform. Covers state refresh, state rm, drift detection, import, and prevention with termination protection.

Table of Contents

Quick Answer

# Terraform auto-detects the deletion — just plan and apply
terraform plan    # Shows: "read during apply" or "will be created"
terraform apply   # Recreates the missing resource

The Error

Error: reading EC2 Instance (i-0abc123def456): couldn't find resource

Error: error reading S3 Bucket (my-bucket): NoSuchBucket: The specified bucket does not exist

Warning: Value for undeclared variable — The resource aws_instance.web no longer exists

Or during refresh:

aws_instance.web: Refreshing state... [id=i-0abc123def456]
aws_instance.web: Resource not found, removing from state

What Causes This

Someone (or something) deleted the resource outside of Terraform:

  • Deleted via AWS Console manually
  • Deleted by another automation tool (CloudFormation, Ansible, scripts)
  • Auto-scaling terminated the instance
  • AWS terminated a spot instance
  • Account cleanup or organization policies

Solution 1: Let Terraform Recreate It

# Terraform detects the deletion during refresh
terraform plan
# aws_instance.web has been deleted
- resource "aws_instance" "web" {
    - id = "i-0abc123def456"
    ...
  }

# aws_instance.web will be created
+ resource "aws_instance" "web" {
    + id = (known after apply)
    ...
  }
terraform apply   # Recreates the resource

This is the cleanest fix — Terraform handles it automatically.

Solution 2: Remove from State (Don’t Recreate)

If you don’t want the resource anymore:

# Remove the resource from Terraform state
terraform state rm aws_instance.web

# Now remove the resource block from your .tf files
# Then plan to verify
terraform plan

Solution 3: Import a Replacement

If someone recreated the resource with a different ID:

# Import the new resource
terraform import aws_instance.web i-0newid789

# Or use import block (Terraform 1.5+)
import {
  to = aws_instance.web
  id = "i-0newid789"
}

Solution 4: Refresh-Only Plan

Detect all drift without making changes:

terraform plan -refresh-only
Note: Objects have changed outside of Terraform

Terraform detected the following changes made outside of Terraform:

  # aws_instance.web has been deleted
  - resource "aws_instance" "web" { ... }

  # aws_security_group.web has been changed
  ~ resource "aws_security_group" "web" {
      ~ ingress = [
          + { from_port = 3389, ... }  # Someone added RDP access
        ]
    }

Apply the refresh to update state without changing infrastructure:

terraform apply -refresh-only

Prevention: Protect Critical Resources

Terraform Lifecycle

resource "aws_db_instance" "main" {
  # ...
  lifecycle {
    prevent_destroy = true
  }
}

This prevents terraform destroy from deleting it, but doesn’t protect against console deletion.

AWS Termination Protection

resource "aws_instance" "critical" {
  instance_type           = "t3.large"
  disable_api_termination = true   # Can't delete via API/console

  tags = {
    Name = "critical-service"
  }
}

resource "aws_db_instance" "main" {
  deletion_protection = true   # RDS deletion protection
}

resource "aws_s3_bucket" "important" {
  # Use object lock or bucket policy to prevent deletion
}

Drift Detection in CI/CD

# Nightly drift detection
drift-check:
  stage: monitor
  script:
    - terraform init
    - terraform plan -refresh-only -detailed-exitcode
    # Exit code 2 = drift detected
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule"
  allow_failure: true

-detailed-exitcode returns:

  • 0 — no changes
  • 1 — error
  • 2 — changes detected (drift)

Hands-On Courses

Conclusion

When resources are deleted outside Terraform, just run terraform plan — it detects the deletion and offers to recreate. Use terraform state rm if you don’t want it back, or terraform import if it was replaced. Prevent drift with disable_api_termination, deletion_protection, and nightly terraform plan -refresh-only in CI.

🚀

Level Up Your Terraform Skills

Hands-on courses, books, and resources from Luca Berton

Luca Berton
Written by

Luca Berton

DevOps Engineer, AWS Partner, Terraform expert, and author. Creator of Ansible Pilot, Terraform Pilot, and CopyPasteLearn.