Terraform Resource Address Parser

Break an address into its steps: the module path first, the resource last. Two things here are what actually break terraform state and -target commands, and neither produces a helpful error.

Paste below, or drop a file anywhere on this panel

Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.

The answer appears here

Paste on the left and press Parse. Nothing leaves this tab.

Examples

Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.

A for_each key inside a module

Two steps, a stable key, and brackets that need quoting on the command line

module.vpc.aws_subnet.private["eu-west-1a"]

An attribute on the end

Valid as an expression and rejected as an address, and the error names the resource

aws_instance.web.id

A count index

Positional, so removing an earlier element makes this address point somewhere else

aws_instance.web[0]

Common mistakes

These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.

  1. Passing an address with an attribute on the end

    terraform state show aws_instance.web.id reports that no such resource is in state. The address is fine up to the attribute, so the error points at the wrong thing.

    Instead:Drop everything after the resource name. Keep the attribute only inside expressions.

  2. Not quoting an address that contains brackets

    zsh fails on the glob before Terraform runs; bash silently strips the double quotes and hands Terraform a different address.

    Instead:Always single-quote the whole address: terraform state rm 'module.a["k"]'.

  3. Reading a count index as a stable identity

    web[1] is the second element of a list, not a particular server. Removing web[0] renumbers everything, so the addresses now point at different objects.

    Instead:Use for_each keyed by something meaningful when the collection can change in the middle.

An address is not an expression, and your shell has opinions about brackets

Addresses look like the references you write in configuration and are a narrower thing. The two differences below are where the time goes.

An attribute is not part of the address

aws_instance.web.id is a valid expression and not a valid address. terraform state show and -target want the resource, so the trailing .id makes them report a resource that does not exist, which reads like a state problem rather than one extra component.

Brackets are shell metacharacters

terraform state rm module.a["k"] unquoted: zsh fails on the glob before Terraform starts, and bash strips the double quotes so Terraform receives an address that is not what you typed. Wrap the whole address in single quotes, every time, and the problem disappears.

A numeric key means count and is positional

aws_instance.web[0] is the first element of a count. Remove an earlier element and every later index shifts, so this address now names a different object and Terraform destroys and recreates the tail of the list. That is the reason to prefer for_each.

A string key means for_each and is stable

aws_subnet.private["eu-west-1a"] keeps its identity when other keys are added or removed. The key is part of the address, so choosing keys that mean something makes state readable years later.

A module address is valid for some commands and not others

-target and state list accept module.vpc and act on everything inside it. state show needs a single object and rejects it. Targeting a module is a bigger hammer than people expect, since it pulls in every resource the module declares.

A data source is in state and is not managed

data.aws_ami.ubuntu appears in state list, which inflates the count and confuses cleanup. It is re-read every plan, so removing it from state changes nothing, and destroy ignores it entirely.

More terraform tools

Terraform Validator & Formatter Does it parse, and is it formatted? Terraform dynamic Block Generator It is ingress.value, not each.value Terraform check and precondition Generator A failed check does not stop the apply Terraform variables.tf Generator From the var. references you already wrote Terraform Unused Declaration Linter Dead variables, locals and data sources Terraform Atlantis YAML Generator when_modified misses your modules Terraform Function Tester and HCL Console terraform console, in a tab Terraform for Expression Tester Where do the keys collide? Terraform Interpolation Tester null becomes an empty string Terraform templatefile Tester Render it before you apply it Terraform Resource Count Calculator How many objects, not how many blocks Terraform count to for_each Converter With the moved blocks it needs Terraform moved Block Generator Rename without destroying Terraform state mv Command Builder No plan, no undo Terraform target Flag Builder And why to stop using it Terraform outputs.tf Generator Outputs are not sensitive by default Terraform Remote State Data Source Generator It grants read of the whole state Terraform Provider Block Generator docker is not hashicorp/docker Terraform .gitignore Generator and Checker .terraform* eats the lock file Terraform to OpenTofu Migration Checker The state is the part to watch Terraform tfvars to JSON Converter The JSON file wins Terraform Version Constraint Parser What ~> actually allows Terraform cidrsubnet Calculator newbits is added, not the target Terraform Import Block Generator The id is not the name Terraform Lock File Viewer Why CI fails and your laptop does not Terraform Variables Checker A missing value hangs CI Terraform tfvars to Env Vars Converter Lists and maps have to be JSON Terraform Deprecated Syntax Checker What a current Terraform rejects Terraform State File Viewer Read it without uploading it Terraform Plan JSON Viewer It is not redacted Terraform HCL to JSON Converter And what the conversion loses Terraform Module Source Validator version only works for the registry Terraform Backend Config Decoder Is state actually locked? Terraform Naming Convention Validator A hyphen makes a resource unreferenceable

Elsewhere on the site