Repository navigation
Use resource identity to detect two state entries tracking the same remote object #39332
Description
TL;DR
State can silently hold two addresses bound to one remote object. When that happens, terraform plan shows a routine-looking destroy that actually targets live infrastructure, with no hint that the object is also tracked elsewhere. An earlier ID-based duplicate check was deliberately relaxed (#33390 → #33434) because raw import IDs are not a sound uniqueness key — but resource identity (v1.12+) is exactly that key, and HCP Terraform already uses it in its bulk-import workflow to detect objects managed by another workspace. I propose bringing the same detection into core, within a single state: warn at plan time when two managed instances share an identity, and at import time when the imported object is already tracked.
Use Cases
A real incident:
- An AWS Secrets Manager secret was bound to a root-level address, likely via an old ad-hoc
terraform importor a local apply of uncommitted config. - The same secret is properly managed by a module instance (
module.app.aws_secretsmanager_secret.rds_password). State ended up with two entries pointing to one remote object. - The root-level address had no configuration, so
planproposed adestroy. Applying it would have scheduled deletion of the live secret referenced by running ECS tasks. - Nothing in the plan output indicated the duplication. A human reviewer caught it by noticing the name collision.
Duplicate tracking commonly arises from CLI import to a second address, local applies of never-merged config, or module refactors that import into the new address without removing the old entry. The resulting destroy diffs are indistinguishable from legitimate ones.
The import documentation states the assumption but nothing enforces it:
Terraform expects that each remote object it is managing will be bound to only one resource address. (...) If you import the same object multiple times, Terraform may exhibit unwanted behavior.
Current Behavior
planperforms no duplicate detection across state entries.- CLI
terraform importperforms no check against existing state. - Config-driven import validates only duplicate target addresses among
importblocks:internal/configs/module.goemits"Duplicate import configuration for %q"when two blocks share atoaddress. An earlier ID-based duplicate check was deliberately relaxed in configs: remove import block duplicate id check #33434 (closing "import" block validation is failing on false-positive "duplicates" #33390), on the grounds that raw ID strings are not unique: abstract resources such astime_sleeplegitimately return identical import responses for distinct instances, and as noted there, "Terraform cannot enforce any uniqueness in resources" from the ID alone. - HCP Terraform uses resource identities in its bulk-import workflow "to determine when resources are managed by another workspace" (bulk import docs). The detection capability exists; it is not applied within a single state in core.
Proposal
Resource identity (v1.12+) resolves the objection that led to relaxing the earlier check. Unlike a raw ID string, an identity is provider-defined with a documented uniqueness contract: it "must correspond to at most one remote object per provider" (identity docs). Core already persists it per instance: ResourceInstanceObject.Identity is serialized into state as IdentityJSON with IdentitySchemaVersion (internal/states/instance_object.go). So the data needed for comparison is already in state.
- Plan time (primary): warn when two managed instances of the same resource type in the same state share an identity, naming both addresses. This catches pre-existing duplicates — like the incident above — exactly when a reviewer is looking at the dangerous destroy.
- Import time: apply the same check when an
importblock or CLIterraform importtargets an object whose identity matches an existing managed instance.
Scope the check to resource types whose provider defines an identity schema, and skip the rest. That avoids re-introducing the #33390 false positives by construction: abstract resources like time_sleep have no meaningful remote identity and would simply not participate. Defaulting to a warning rather than a hard error keeps intentional workflows (e.g. deliberate co-management patterns) working, while making the documented assumption visible when violated. A flag could opt into an error.
Attempted Solutions
- Process discipline (only reviewed
importblocks, no local applies). This does not catch duplicates already present in state. - External audit in CI:
terraform state pull | jq, grouping instances by(type, id). This works, but every team reinvents it, and raw string IDs are exactly what configs: remove import block duplicate id check #33434 established as unsound — and what resource identity was introduced to improve on.
Terraform Version
n/a — feature request; behavior confirmed against v1.16 documentation and current main source.
References
- Import docs warning — "bound to only one resource address"
- "import" block validation is failing on false-positive "duplicates" #33390 / configs: remove import block duplicate id check #33434 — the earlier ID-based duplicate check among
importblocks and why it was relaxed to ato-address check internal/configs/module.go— current duplicate-tovalidation;internal/states/instance_object.go— identity persisted in state- Resource identity concepts — implementable in both the Plugin Framework and SDKv2, so coverage extends to legacy-SDK providers
- Bulk import — HCP's cross-workspace detection via identity
- Auto-import existing resources matching the configuration #29160 — related: auto-import of existing resources matching configuration
Activity
crw commentedon Oct 6, 2026
Thanks for this feature request! If you are viewing this issue and would like to indicate your interest, please use the 👍 reaction on the issue description to upvote this issue. We also welcome additional use case descriptions. Thanks again!
apparentlymart commentedon Oct 6, 2026
Just as some historical context, I believe this issue is describing the idea I wrote under "Detecting Object Collisions" in #22094.
In particular, I wrote:
This issue proposes making this situation be reported as a warning rather than an error so that it doesn't block other changes, which seems reasonable.
I think there's still an unanswered question of what exactly the operator ought to do when they encounter this warning. If they encounter it at plan time before the duplicate bindings exist in the state then of course what they ought to do is not apply the plan. But there are at least a few situations where this would be detected only after the duplicate binding was already persisted in a state snapshot, such as:
In these situations I think it's important not to guide the operator into the trap of just deleting the duplicate
resourceblocks and runningterraform apply, because that would then delete the underlying object completely and invalidate the one binding the operator actually wanted to keep.A manual solution would be to add a
removedblock for each removedresourceblock that explicitly disables destroying:...but when I wrote that earlier issue I was considering that Terraform could perhaps detect this situation -- where the resource identity of an object proposed for deletion matches the resource identity of another object that's still in the desired state -- and either automatically treat it as if
destroy = false, or to emit another warning/error suggesting that the operator should add aremovedblock like the above.