OpenTofu Error: 'Resource already exists' — Cause, Fix, and Troubleshooting Guide
Fix OpenTofu 'Error: ... already exists' on apply by importing the existing object into state with tofu import or an import block.
- #opentofu
- #iac
- #troubleshooting
- #errors
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
When tofu apply tries to create a resource whose real-world object already exists — a bucket name, an IAM role, a security group — the cloud API rejects the create and OpenTofu surfaces the provider’s “already exists” error. State does not know about the object, so OpenTofu tried to make a new one:
Error: creating S3 Bucket (example-prod-logs): BucketAlreadyOwnedByYou:
Your previous request to create the named bucket succeeded and you already
own it.
with aws_s3_bucket.logs,
on main.tf line 3, in resource "aws_s3_bucket" "logs":
3: resource "aws_s3_bucket" "logs" {
Symptoms
tofu applyfails on create with a provideralready exists/AlreadyExists/EntityAlreadyExistserror.- State has no record of the resource, but the cloud object is really there.
- Common when adopting existing infrastructure, or after a partial/failed apply.
- Re-running apply keeps failing the same way.
Common Root Causes
- Object created out-of-band — made manually or by another tool.
- State lost or not shared — the resource was applied elsewhere with different state.
- Partial apply — a prior run created the object but failed before writing state.
- Name collision — a globally unique name (S3, IAM) already taken by you or another account.
- Duplicated config created the same real resource under two addresses.
How to diagnose
Confirm the object exists and get its ID for import:
aws s3api head-bucket --bucket example-prod-logs
aws iam get-role --role-name example-app-role
Check whether state already tracks it (it should not, if you got this error):
tofu state list | grep logs
Find the import ID format for the resource type in the provider docs, then proceed.
Fixes
Import the existing object into state so OpenTofu manages it instead of recreating it. Imperative form:
tofu import aws_s3_bucket.logs example-prod-logs
Declarative import block (reviewable, plan-first):
import {
to = aws_s3_bucket.logs
id = "example-prod-logs"
}
tofu plan # shows the import and any config diffs
tofu apply
Or rename to a genuinely new object if you did not mean to adopt the existing one:
resource "aws_s3_bucket" "logs" {
bucket = "example-prod-logs-v2"
}
Verify config matches the imported object so the next plan is clean:
tofu plan
What to watch out for
- After import, reconcile config to the real object’s settings or the next plan will propose changes.
importblocks are preferable in teams — they are code-reviewed and run during plan.- Globally unique names (S3 buckets, IAM) can collide across accounts; a rename may be the only option.
- A recurring “already exists” often means state is not shared — check your backend before importing everywhere.
Related
- OpenTofu Error: ‘Objects have changed outside of OpenTofu’ — Cause, Fix, and Troubleshooting Guide
- OpenTofu Error: ‘Provider configuration not present’ — Cause, Fix, and Troubleshooting Guide
- OpenTofu Error: ‘Error acquiring the state lock’ — Cause, Fix, and Troubleshooting Guide
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.