| Tested on | Ubuntu 26.04 LTS (Resolute Raccoon) |
|---|---|
| Package | terraform 1.15.8-1 |
| Applies to | Any host with Terraform installed |
| Lab environment | Single Ubuntu VM with Terraform — Terraform lab environment on Ubuntu |
| Privilege | Normal user; sudo only if Terraform is not installed yet |
| Scope | Troubleshooting Terraform Unsupported attribute — wrong object attribute names, missing module outputs, count and for_each module shape changes, terraform_remote_state output references, terraform console diagnostics with type, keys, and value inspection, and optional attribute patterns. Does not cover full object type tutorials or provider schema design. |
| Related guides | Terraform module inputs and outputs Terraform output Terraform data types terraform console Invalid index error fixes |
Unsupported attribute means Terraform found the value you referenced, but that value has no field with the name you asked for. The message is explicit:
This object does not have an attribute named "..."Unlike a missing resource or undeclared variable, the object itself evaluated fine. The fix is to match the actual shape — object keys, module output names, or indexed module instances — not to delete state or wrap every dot in try().
Each scenario below uses its own directory under ~/terraform-labs/terraform-unsupported-attribute-error/.
terraform_data resource and small local modules. Run terraform init in each new directory before terraform validate or terraform plan.
What Unsupported attribute means in Terraform
Terraform distinguishes attribute access (.name) from index access (["key"] or [0]). When you write var.server.hostname but the object only defines name and port, validate fails with Unsupported attribute:
Error: Unsupported attribute
on main.tf line 7, in resource "terraform_data" "svc":
7: input = var.server.hostname
├────────────────
│ var.server is a object
This object does not have an attribute named "hostname".The hint line (var.server is a object) tells you Terraform resolved var.server — the problem is the attribute name, not whether the variable exists.
Common shapes behind this error:
| You wrote | Value Terraform found | Typical fix |
|---|---|---|
var.server.hostname |
object with name, port |
use var.server.name |
module.app.id |
object with no attributes | add output in child module |
module.app.id |
list of module objects (count) |
use module.app[0].output_name |
module.app.id |
object with key "web" (for_each) |
use module.app["web"].output_name |
remote_state.outputs.wrong_name |
outputs object with app_name |
use the real root output name |
When the error mentions a list of object or numeric index on an object, see Invalid index error fixes — that is a different lookup failure.
Inspect the object with terraform console
Before renaming attributes at random, print what Terraform actually holds. terraform console evaluates expressions against the current configuration without changing state.
mkdir -p ~/terraform-labs/terraform-unsupported-attribute-error/fixes/console-diagnostics
cd ~/terraform-labs/terraform-unsupported-attribute-error/fixes/console-diagnosticsSeed a local object for inspection:
cat > main.tf <<'EOF'
terraform {
required_version = ">= 1.12.0"
}
locals {
server = { name = "web-1", port = 80 }
}
EOFInitialize the working directory:
terraform init -input=falseAsk console for the structural type:
echo 'type(local.server)' | terraform console -no-colorobject({
name: string,
port: number,
})Print the value itself:
echo 'local.server' | terraform console -no-color{
"name" = "web-1"
"port" = 80
}List attribute names when you need a quick checklist:
echo 'keys(local.server)' | terraform console -no-color[
"name",
"port",
]hostname never appears in that list, so any reference to local.server.hostname will keep failing until you align the name or extend the object type.
Fix wrong object attribute names
Object types declare which keys exist. A typo or renamed field in application code often surfaces as Unsupported attribute on var.server.hostname when only name and port are defined.
mkdir -p ~/terraform-labs/terraform-unsupported-attribute-error/errors/object-attribute
cd ~/terraform-labs/terraform-unsupported-attribute-error/errors/object-attributeReproduce the typo — note commas inside object({ ... }), not semicolons:
cat > main.tf <<'EOF'
terraform {
required_version = ">= 1.12.0"
}
variable "server" {
type = object({
name = string
port = number
})
default = {
name = "web-1"
port = 80
}
}
resource "terraform_data" "svc" {
input = var.server.hostname
}
EOFInitialize and validate:
terraform init -input=falseTerraform has been successfully initialized!Run validate to surface the missing attribute:
terraform validate -no-colorError: Unsupported attribute
on main.tf line 7, in resource "terraform_data" "svc":
7: input = var.server.hostname
├────────────────
│ var.server is a object
This object does not have an attribute named "hostname".Use an attribute that exists on the object. For Terraform data types detail on object constraints, keep the type and the references aligned:
input = var.server.nameCopy the fix pattern to a sibling directory:
mkdir -p ~/terraform-labs/terraform-unsupported-attribute-error/fixes/object-attribute
cd ~/terraform-labs/terraform-unsupported-attribute-error/fixes/object-attributeWrite main.tf with var.server.name instead of the mistyped attribute:
cat > main.tf <<'EOF'
terraform {
required_version = ">= 1.12.0"
}
variable "server" {
type = object({
name = string
port = number
})
default = {
name = "web-1"
port = 80
}
}
resource "terraform_data" "svc" {
input = var.server.name
}
EOFConfirm the configuration is valid:
terraform init -input=false && terraform validate -no-colorSuccess! The configuration is valid.Check spelling and case exactly — Name and name are different attributes on strict object types.
Fix unsupported attribute on module outputs
A child module's resources are private. module.app in the parent is an object of exported outputs only, not a handle to internal resources.
mkdir -p ~/terraform-labs/terraform-unsupported-attribute-error/errors/module-missing-output/modules/app
cd ~/terraform-labs/terraform-unsupported-attribute-error/errors/module-missing-outputChild module with no outputs:
cat > modules/app/main.tf <<'EOF'
variable "name" {
type = string
}
resource "terraform_data" "x" {
input = var.name
}
EOFParent references a non-existent id output:
cat > main.tf <<'EOF'
module "app" {
source = "./modules/app"
name = "web"
}
resource "terraform_data" "ref" {
input = module.app.id
}
EOFValidate shows the empty module object:
terraform init -input=false && terraform validate -no-colorError: Unsupported attribute
on main.tf line 6, in resource "terraform_data" "ref":
6: input = module.app.id
├────────────────
│ module.app is object with no attributes
This object does not have an attribute named "id".Export the value from the child module. See Terraform module inputs and outputs for the full wiring pattern:
output "instance_id" {
value = terraform_data.x.id
}Reference the output name from the parent:
input = module.app.instance_idCopy the corrected wiring to a sibling directory:
mkdir -p ~/terraform-labs/terraform-unsupported-attribute-error/fixes/module-output/modules/app
cd ~/terraform-labs/terraform-unsupported-attribute-error/fixes/module-outputChild module with the exported output:
cat > modules/app/main.tf <<'EOF'
variable "name" {
type = string
}
resource "terraform_data" "x" {
input = var.name
}
output "instance_id" {
value = terraform_data.x.id
}
EOFParent references instance_id:
cat > main.tf <<'EOF'
module "app" {
source = "./modules/app"
name = "web"
}
resource "terraform_data" "ref" {
input = module.app.instance_id
}
EOFConfirm the configuration is valid:
terraform init -input=false && terraform validate -no-colorSuccess! The configuration is valid.Fix count and for_each module addressing
count and for_each on a module block change the type of module.NAME in the parent. A single module instance is a plain output object; count turns it into a list; for_each turns it into a map keyed by instance.
count turns the module into a list
Start in a fresh directory for the counted-module shape error:
mkdir -p ~/terraform-labs/terraform-unsupported-attribute-error/errors/count-module-shape/modules/app
cd ~/terraform-labs/terraform-unsupported-attribute-error/errors/count-module-shapeChild module with an instance_id output:
cat > modules/app/main.tf <<'EOF'
variable "name" {
type = string
}
resource "terraform_data" "x" {
input = var.name
}
output "instance_id" {
value = terraform_data.x.id
}
EOFParent module block uses count = 1 but still references module.app.id:
cat > main.tf <<'EOF'
module "app" {
count = 1
source = "./modules/app"
name = "web"
}
resource "terraform_data" "ref" {
input = module.app.id
}
EOFValidate reports a list, not a missing output name:
terraform init -input=false && terraform validate -no-colorError: Unsupported attribute
on main.tf line 7, in resource "terraform_data" "ref":
7: input = module.app.id
├────────────────
│ module.app is a list of object
Can't access attributes on a list of objects. Did you mean to access an
attribute for a specific element of the list, or across all elements of the
list?Index the module instance first, then read the output:
input = module.app[0].instance_idCopy the corrected addressing to a sibling directory:
mkdir -p ~/terraform-labs/terraform-unsupported-attribute-error/fixes/count-module/modules/app
cd ~/terraform-labs/terraform-unsupported-attribute-error/fixes/count-moduleChild module with the same instance_id output:
cat > modules/app/main.tf <<'EOF'
variable "name" {
type = string
}
resource "terraform_data" "x" {
input = var.name
}
output "instance_id" {
value = terraform_data.x.id
}
EOFParent indexes the counted module instance:
cat > main.tf <<'EOF'
module "app" {
count = 1
source = "./modules/app"
name = "web"
}
resource "terraform_data" "ref" {
input = module.app[0].instance_id
}
EOFConfirm the configuration is valid:
terraform init -input=false && terraform validate -no-colorSuccess! The configuration is valid.for_each turns the module result into a map of instances
With for_each, module.app is a map of module result objects keyed by the for_each keys ("web", "api", …). Access an instance with bracket notation, then read an output name from that instance.
mkdir -p ~/terraform-labs/terraform-unsupported-attribute-error/errors/foreach-module-shape/modules/app
cd ~/terraform-labs/terraform-unsupported-attribute-error/errors/foreach-module-shapeChild module with an instance_id output:
cat > modules/app/main.tf <<'EOF'
variable "name" {
type = string
}
resource "terraform_data" "x" {
input = var.name
}
output "instance_id" {
value = terraform_data.x.id
}
EOFRoot module keeps module.app.id so plan surfaces the Unsupported attribute on the module map:
cat > main.tf <<'EOF'
module "app" {
for_each = toset(["web"])
source = "./modules/app"
name = each.key
}
resource "terraform_data" "ref" {
input = module.app.id
}
EOFterraform validate can succeed here because module expansion is deferred. The Unsupported attribute appears during plan:
terraform init -input=false && terraform plan -no-colorError: Unsupported attribute
on main.tf line 7, in resource "terraform_data" "ref":
7: input = module.app.id
├────────────────
│ module.app is object with 1 attribute "web"
This object does not have an attribute named "id".Terraform is telling you module.app has a "web" key — drill into that instance, then into the output:
input = module.app["web"].instance_idFor keyed instances versus numeric indexes, compare with Terraform count vs for_each.
Fix terraform_remote_state output references
data.terraform_remote_state exposes only root-module outputs from another state file. The outputs attribute is itself an object — wrong output names produce the same Unsupported attribute message as a typo on var.server.
Create a producer stack that writes app_name to state:
mkdir -p ~/terraform-labs/terraform-unsupported-attribute-error/remote-state/producer
cd ~/terraform-labs/terraform-unsupported-attribute-error/remote-state/producerProducer main.tf declares only the app_name root output:
cat > main.tf <<'EOF'
terraform {
backend "local" {
path = "terraform.tfstate"
}
}
output "app_name" {
value = "web-producer"
}
EOFApply so the output exists in the producer state:
terraform init -input=false && terraform apply -auto-approve -no-colorApply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
app_name = "web-producer"Consumer stack with a mistyped output name:
mkdir -p ~/terraform-labs/terraform-unsupported-attribute-error/errors/remote-state-consumer
cd ~/terraform-labs/terraform-unsupported-attribute-error/errors/remote-state-consumerConsumer main.tf reads outputs.wrong_name instead of the real app_name:
cat > main.tf <<'EOF'
terraform {
backend "local" {
path = "terraform.tfstate"
}
}
data "terraform_remote_state" "producer" {
backend = "local"
config = {
path = "${path.module}/../../remote-state/producer/terraform.tfstate"
}
}
resource "terraform_data" "ref" {
input = data.terraform_remote_state.producer.outputs.wrong_name
}
EOFPlan reads the remote state, then fails on the output object:
terraform init -input=false && terraform plan -no-colordata.terraform_remote_state.producer: Reading...
data.terraform_remote_state.producer: Read complete after 0s
Error: Unsupported attribute
on main.tf line 13, in resource "terraform_data" "ref":
13: input = data.terraform_remote_state.producer.outputs.wrong_name
├────────────────
│ data.terraform_remote_state.producer.outputs is object with 1 attribute "app_name"
This object does not have an attribute named "wrong_name".The diagnostic names the only available output — change the reference to match the producer's root output block:
input = data.terraform_remote_state.producer.outputs.app_nameList outputs with console when the producer is not yours: data.terraform_remote_state.NAME.outputs in the console, or terraform output in the producer directory. For backend setup context, see Terraform backends and remote state.
Optional attributes without masking typos
When a field is genuinely optional, design it into the type instead of sprinkling try() on every access:
optional(string)inside anobject({ ... })type constraint (Terraform 1.3+)lookup(map, "key", default)for map keys that may be absenttry(expr, fallback)only whennullor a default is acceptable business logic
Do not use try(var.server.hostname, var.server.name) to paper over a renamed field — that hides the typo and makes refactors harder. Fix the attribute name or extend the object type so hostname is declared when it is required.
Diagnostic checklist
| Step | What to run or check |
|---|---|
| Inspect value | terraform console → local.example or var.example |
| Inspect type | type(local.example) — object, list, or map of module results |
| List object keys | keys(local.example) — exact spelling and case |
| Module outputs | child outputs.tf / output blocks; parent uses module.NAME.output_name |
| count module shape | module.NAME[0].output_name, not module.NAME.output_name |
| for_each module shape | module.NAME["key"].output_name, not module.NAME.output_name |
| Remote state | producer terraform output; consumer uses .outputs.<root_output_name> |
Verify the fix
After correcting the attribute, output name, or module index, validate and plan in the fix directory:
cd ~/terraform-labs/terraform-unsupported-attribute-error/fixes/object-attribute
terraform validate -no-color && terraform plan -no-colorSuccess! The configuration is valid.
Plan: 1 to add, 0 to change, 0 to destroy.Destroy lab resources when you finish:
cd ~/terraform-labs/terraform-unsupported-attribute-error/remote-state/producer && terraform destroy -auto-approve -input=false 2>/dev/null || trueReferences
- Attribute access — HashiCorp Developer
- Module output blocks — HashiCorp Developer
- terraform_remote_state data source — HashiCorp Developer
- Type constraints for objects — HashiCorp Developer
Summary
Unsupported attribute means Terraform evaluated the object or module reference, but the name after the dot does not exist on that value. Object typos such as var.server.hostname when only name is defined fail at validate time; missing module outputs show module.app is object with no attributes until you export the value from the child module.
count and for_each change module addressing — a counted module is a list (module.app[0].instance_id), and a for_each module is addressed by key, such as module.app["web"].instance_id. Remote state failures look the same on outputs.wrong_name when the producer only exports app_name.
Use terraform console with type(), keys(), and direct value prints before you rename attributes at random. Prefer fixing names and outputs over wrapping expressions in try() — optional types and lookup() belong where absence is real, not where you have a spelling mistake.
For bracket and index failures on the same collections, continue with Invalid index error fixes. For declaring outputs and module contracts, see Terraform output.

