Skip to content
DevOps AI ToolKit
Newsletter
All guides
AI for Terraform By James Joyner IV · · 9 min read

Terraform Error Guide: 'Invalid default value for variable' — Align the Default With the Type Constraint

Quick answer

Fix 'Invalid default value for variable' in Terraform by matching the default to its type constraint: string vs number, list vs set, and object attributes.

  • #terraform
  • #iac
  • #troubleshooting
  • #errors
Free toolkit

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

Terraform validates every variable block during the earliest configuration-loading phase, before it plans or refreshes anything. If a variable declares a type constraint and also a default, Terraform checks that the default is convertible to that type. When it is not, evaluation stops immediately with a diagnostic that points at the offending default line:

Error: Invalid default value for variable

  on variables.tf line 4, in variable "instance_count":
   4:   default = "three"

This default value is not compatible with the variable's type constraint:
a number is required.

The exact tail of the message changes with the constraint — a number is required, a bool is required, list of string required, attribute "port" is required, and so on — but the header Invalid default value for variable is constant. Because this runs so early, none of your resources, data sources, or provider blocks are even parsed yet: Terraform refuses to proceed until the declared default and the declared type agree.

Symptoms

  • terraform plan, terraform validate, or terraform apply aborts instantly with Invalid default value for variable, before any provider is configured.
  • The diagnostic names a specific variable block and its default = line.
  • The final sentence states what type was required (a number is required, a bool is required, list of object required, etc.).
  • Passing the same value in explicitly via -var or a .tfvars file produces the sibling error Invalid value for input variable instead.
  • Removing the type constraint (or removing the default) makes the error disappear — confirming it is a type/default mismatch, not a syntax problem.

Common Root Causes

  • Quoted numbers or booleans. default = "3" or default = "true" where the type is number / bool. Strings do not auto-convert to numbers here.
  • Wrong collection kind. Supplying a list default for a set(string), or a map default for an object(...), or [] where a map is required.
  • Object attribute mismatch. An object({ ... }) type whose default is missing a required attribute, has an extra unknown attribute, or gives an attribute the wrong element type.
  • null against a non-nullable type. default = null when the variable is declared nullable = false.
  • Empty-collection ambiguity. default = {} for a list(...) type (or [] for a map(...)) — the empty literal is the wrong collection kind.
  • optional() misuse. Marking an attribute optional() but then supplying a default object that still omits a required (non-optional) attribute.

Diagnostic Workflow

Run validate first — it surfaces the error without touching state or a backend:

terraform init -backend=false
terraform validate
terraform console   # interactively test what a value converts to

Inspect the variable declaration and its default side by side. A classic failing case — a number type with a quoted string default:

variable "instance_count" {
  type    = number
  default = "three"   # string, not convertible to number
}

An object type whose default omits a required attribute:

variable "network" {
  type = object({
    name = string
    cidr = string
    port = number
  })

  default = {
    name = "core"
    cidr = "10.0.0.0/16"
    # port is missing -> "attribute \"port\" is required"
  }
}

Use terraform console to prove what a literal converts to before you commit it to the file:

echo 'tonumber("three")' | terraform console   # error: cannot convert
echo 'tonumber("3")'     | terraform console   # 3
echo 'toset(["a","a","b"])' | terraform console

Example Root Cause Analysis

A team parameterized an autoscaling group and wanted the count to be tunable, so they wrote:

variable "instance_count" {
  type    = number
  default = "3"
}

terraform validate failed with a number is required. The author assumed HCL would coerce the quoted "3" the way many templating languages do. It does not: the default is evaluated against the number constraint literally, and a string value "3" is not the same as the number 3. The fix is to drop the quotes so the literal is a number:

variable "instance_count" {
  type    = number
  default = 3
}

The same class of bug bit a second variable, tags, declared as map(string) but defaulted to a list:

variable "tags" {
  type    = map(string)
  default = ["env", "prod"]   # list, not a map
}

Corrected to a map literal:

variable "tags" {
  type = map(string)
  default = {
    env = "prod"
  }
}

After both edits, terraform validate returned Success! The configuration is valid. and plan proceeded normally.

Prevention Best Practices

  • Never quote numbers or booleans you intend as number / bool defaults — write 3 and true, not "3" and "true".
  • Match the collection kind exactly: [] only for list/set/tuple, {} only for map/object. Use type = list(string) with default = [] and type = map(string) with default = {}.
  • Keep object defaults in lockstep with the object type — every required (non-optional()) attribute must appear, with the right element type, and no unknown attributes.
  • Use optional(type, fallback) for attributes that genuinely may be absent, instead of hand-rolling partial default objects.
  • Run terraform validate in CI on every push so a type/default mismatch is caught before review, not at apply time.
  • Prefer explicit types on every variable; an untyped variable accepts anything and simply defers the error to where the value is used, which is harder to debug.

Quick Command Reference

# Validate configuration without a backend or state
terraform init -backend=false
terraform validate

# Machine-readable diagnostics (useful in CI)
terraform validate -json

# Test what a literal converts to before editing the file
terraform console
#   > tonumber("3")
#   > toset(["a","b"])
#   > { name = "core", port = 8080 }

# Format the file so structural mistakes are easier to spot
terraform fmt

# Re-plan once the default matches its type
terraform plan

Conclusion

Invalid default value for variable is a pure type-mismatch check that runs before Terraform does any real work: the value in default must be convertible to the variable’s declared type. The overwhelmingly common causes are quoting numbers or booleans, using the wrong collection kind ([] vs {}), and object defaults that omit a required attribute. Read the last line of the diagnostic — it tells you exactly what type was required — then either fix the literal or adjust the type constraint (including optional() for attributes that may be absent). Wire terraform validate into CI and these mismatches never reach an apply.

Free download · 368-page PDF

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.