Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Terraform By James Joyner IV · · 9 min read

Terraform Error Guide: 'Cannot import non-existent remote object' — fix the import ID

Quick answer

Fix 'Cannot import non-existent remote object' in Terraform: correct the import ID format, target the right region/account and provider, and verify the resource actually exists before importing.

  • #terraform
  • #iac
  • #troubleshooting
  • #errors
Free toolkit

Fixing errors like this? Get 500 free DevOps AI prompts

500 copy-paste AI prompts for the stack you actually run — one PDF, free.

Overview

Terraform raises this during an import — either the terraform import command or an import {} block — when the provider looks up the ID you gave and gets nothing back:

Error: Cannot import non-existent remote object

While attempting to import an existing object to "aws_instance.web", the
provider object returned no data. This means the object no longer exists, or
the provided import ID is not valid.

The provider was asked to read a real, existing object by ID, and the read returned empty. Terraform will not fabricate state for something it cannot see, so it stops. The object either genuinely does not exist, exists somewhere the provider is not looking (wrong region, account, or project), or the ID string is in the wrong format for that resource type.

Symptoms

  • terraform import or terraform plan (with an import {} block) fails with Cannot import non-existent remote object.
  • The error names the target address (for example aws_instance.web) and often the ID you supplied.
  • The resource is clearly visible in the cloud console, yet Terraform still says it does not exist.
  • Import works for a colleague but not for you — a credentials, region, or account difference.
  • A bulk import loop succeeds for most resources and fails for a handful with malformed IDs.

Common Root Causes

  • Wrong ID format — many resources expect a composite ID (for example bucket-name/key, vpc-id/subnet-id, or resource_group/name), not just a bare name or ARN.
  • Wrong region or account — the provider is configured for us-east-1 but the object lives in eu-west-1, or a different AWS account/GCP project entirely.
  • Wrong provider alias — a multi-provider config imports against the default provider instead of the aliased one that owns the object.
  • Object really deleted — it was removed after you copied its ID.
  • Insufficient permissions — the identity can list in the console but the API read returns nothing (some providers surface an access issue as “not found”).
  • Using an ARN/URL where an ID is expected, or vice versa.

Diagnostic Workflow

Confirm the object exists from the same credentials Terraform uses, in the same region:

aws sts get-caller-identity          # which account am I actually in?
aws ec2 describe-instances --instance-ids i-0abc123def456 --region us-east-1

Check the exact import ID format the resource expects — it is documented per resource under the provider’s “Import” section. Composite IDs are the usual trap:

# aws_route53_record wants ZONEID_NAME_TYPE, not the record name
import {
  to = aws_route53_record.www
  id = "Z0123456789ABCDEFGHIJ_www.example.com_A"
}

Verify the provider block the import will use — region, profile, and alias:

provider "aws" {
  alias   = "eu"
  region  = "eu-west-1"
  profile = "prod"
}

import {
  to       = aws_s3_bucket.assets
  id       = "acme-prod-assets"
  # the resource must reference provider = aws.eu if it lives in that account/region
}

For the command form, pass explicit variables so region/account are unambiguous:

terraform import aws_s3_bucket.assets acme-prod-assets
# add -var / TF_VAR_ / AWS_PROFILE so the provider targets the right place

Generate config and IDs automatically to avoid hand-typing mistakes:

terraform plan -generate-config-out=generated.tf

Example Root Cause Analysis

An engineer tried to import an S3 bucket policy: terraform import aws_s3_bucket_policy.assets acme-prod-assets. It failed with Cannot import non-existent remote object, even though the bucket was right there in the console.

Two problems surfaced. First, the provider was configured for us-east-1 while the bucket lived in eu-west-1, so the read hit the wrong regional endpoint. Second — the real one — aws_s3_bucket_policy imports by the bucket name, which was correct, but the bucket had no policy attached yet, so there was genuinely no remote object to import. The console showed the bucket, not a policy. The fix was to stop importing a non-existent policy and instead apply the aws_s3_bucket_policy resource to create it. The takeaway: “the resource exists” in the console is not the same as “the specific object this address maps to exists” — import binds one address to one concrete remote object.

Prevention Best Practices

  • Look up the resource’s Import section for the exact ID format before importing — composite IDs are the number-one cause.
  • Verify existence with the provider CLI first, using the same credentials and region Terraform will use.
  • Prefer import {} blocks with -generate-config-out over hand-typed terraform import for repeatable, reviewable imports.
  • Confirm account/region/alias explicitly in multi-provider setups so the read hits the right place.
  • Distinguish the parent from the attachment — importing a bucket is not the same as importing its policy or ACL.
  • Import into a plan first and review before committing state changes.

Quick Command Reference

aws sts get-caller-identity                 # confirm account/identity
terraform plan -generate-config-out=gen.tf  # import blocks -> generated config
terraform import <address> <id>             # command-form import
terraform state list                        # confirm what is already managed
terraform state show <address>              # inspect an imported object

Conclusion

Cannot import non-existent remote object means the provider read your import ID and found nothing — so fix what it is reading. Check that the object truly exists, that your credentials point at the right account and region (or provider alias), and that the ID is in the exact format the resource type expects, composite parts included. Verify with the cloud CLI first, prefer import {} blocks with generated config over hand-typed IDs, and remember that seeing a resource in the console does not guarantee the specific object your address maps to exists.

Free download · 368-page PDF

Get 500 Battle-Tested DevOps AI Prompts — Free

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.