This error occurs when Terraform receives a value of the wrong type for an argument. It commonly happens when passing a list where a string is expected, or wrapping already-typed values in extra brackets.
Terraform is a strongly-typed language. Every resource argument, variable, and module input has a declared type (string, list, map, object, etc.). When you provide a value that doesn't match the expected type, Terraform raises an "unsuitable value type" error. This error most commonly occurs in three scenarios: 1. **Type Mismatch in Arguments**: You're passing a list value to an argument that expects a string, or vice versa. 2. **Wrapping Already-Typed Values**: You're unnecessarily wrapping a list in brackets (e.g., `["list_output"]` instead of just `list_output`). 3. **Nested Type Mismatches**: Object or map arguments have incompatible nested field types. The error message tells you exactly which argument needs fixing and what type is required.
The error will specify which argument is problematic and what type is required. For example:
Error: Inappropriate value for attribute "name": string requiredThis tells you that the name argument expects a string, not the type you provided.
If you're trying to pass a single item from a list, use indexing:
WRONG:
resource "aws_instance" "example" {
subnet_id = var.subnet_ids # List, but subnet_id expects a string
}RIGHT:
resource "aws_instance" "example" {
subnet_id = var.subnet_ids[0] # Get first item from list
}For dynamic selection, use element() function:
resource "aws_instance" "example" {
subnet_id = element(var.subnet_ids, 0)
}If an output is already a list, don't wrap it in brackets:
WRONG:
resource "aws_route_table_association" "private" {
route_table_id = ["module.vpc.private_route_table_ids"] # Extra brackets!
}RIGHT:
resource "aws_route_table_association" "private" {
route_table_id = module.vpc.private_route_table_id # Direct reference
}When a resource expects multiple values (like a list), pass it directly without extra brackets.
Ensure your variable type matches how you use it:
WRONG:
variable "database_name" {
type = string
default = ["mydb"] # Type says string but default is list!
}RIGHT:
variable "database_name" {
type = string
default = "mydb" # Matches the declared type
}Or if you need multiple values:
variable "database_names" {
type = list(string)
default = ["mydb", "otherdb"]
}If you need to convert a list to a string (rarely necessary), Terraform provides functions:
# Join a list into a single string
resource "example" "test" {
names = join(",", var.list_of_names)
}
# Convert to JSON for object arguments
resource "example" "test" {
tags = jsonencode(var.tag_object)
}Terraform 0.12+ Migration Note: When upgrading from Terraform 0.11, type checking became much stricter. Configurations that worked before may need adjustment. Use terraform console to test expressions and verify their types before committing changes.
Type Conversion Strategy: While Terraform can automatically convert between numbers and strings in some cases, it cannot convert lists to strings. If you absolutely need string representation of a list, use jsonencode() or join() instead of relying on implicit conversion.
Module Outputs: When consuming module outputs, check the module's documentation for the exact output type. Module outputs can be strings, lists, maps, or objectsโdon't assume based on the output name.
Error: Error rendering template: template not found
How to fix "template not found" error in Terraform
Error: Error generating private key
How to fix 'Error generating private key' in Terraform
Error creating Kubernetes Service: field is immutable
How to fix "field is immutable" errors in Terraform
Error: Error creating local file: open: permission denied
How to fix "Error creating local file: permission denied" in Terraform
Error: line endings have changed from CRLF to LF
Line endings have changed from CRLF to LF in Terraform