hashicorp/terraform · error
invalid tfvars content: %s
Error message
invalid tfvars content: %s
What it means
Thrown by the built-in `decode_tfvars` function (functions.go:125) when the input string parses as valid HCL but its body cannot be read as tfvars attributes via `f.Body.JustAttributes()`. This happens when the body contains nested blocks or other non-attribute constructs that are legal HCL but illegal in a `.tfvars` file. The error wraps the underlying HCL diagnostic verbatim.
Source
Thrown at internal/builtin/providers/terraform/functions.go:125
// If we get here then we know that:
// - there's exactly one element in args
// - it's a string
// - it is known and non-null
// So therefore the following is guaranteed to succeed.
src := []byte(args[0].AsString())
// As usual when we wrap HCL stuff up in functions, we end up needing to
// stuff HCL diagnostics into plain string error messages. This produces
// a non-ideal result but is still better than hiding the HCL-provided
// diagnosis altogether.
f, hclDiags := hclsyntax.ParseConfig(src, "<decode_tfvars argument>", hcl.InitialPos)
if hclDiags.HasErrors() {
return cty.NilVal, fmt.Errorf("invalid tfvars syntax: %s", hclDiags.Error())
}
attrs, hclDiags := f.Body.JustAttributes()
if hclDiags.HasErrors() {
return cty.NilVal, fmt.Errorf("invalid tfvars content: %s", hclDiags.Error())
}
retAttrs := make(map[string]cty.Value, len(attrs))
for name, attr := range attrs {
// Evaluating the expression with no EvalContext achieves the same
// interpretation as Terraform CLI makes of .tfvars files, rejecting
// any function calls or references to symbols.
v, hclDiags := attr.Expr.Value(nil)
if hclDiags.HasErrors() {
return cty.NilVal, fmt.Errorf("invalid expression for variable %q: %s", name, hclDiags.Error())
}
retAttrs[name] = v
}
return cty.ObjectVal(retAttrs), nil
}
func encodeExprFunc(args []cty.Value) (cty.Value, error) {
// These error checks should not be hit in practice because the languageView on GitHub (pinned to c9def3e214)
Solutions
- Rewrite the input as flat top-level `key = value` attributes only — no nested blocks.
- If the source is JSON, use `jsondecode(...)` instead of `decode_tfvars(...)`.
- If you need nested structures, encode them as HCL values on the right-hand side, e.g. `servers = ["a", "b"]` rather than a block.
- Run `terraform fmt` on the candidate string in a scratch `.tfvars` file to surface the offending construct quickly.
Example fix
// before
decode_tfvars(<<-EOT
env {
name = "prod"
}
EOT
)
// after
decode_tfvars(<<-EOT
env_name = "prod"
EOT
) Defensive patterns
Strategy: validation
Validate before calling
// Pre-validate a tfvars string before handing it to decode_tfvars.
func isValidTfvarsBody(src string) error {
f, diags := hclsyntax.ParseConfig([]byte(src), "<check>", hcl.InitialPos)
if diags.HasErrors() {
return fmt.Errorf("syntax: %s", diags.Error())
}
if _, diags := f.Body.JustAttributes(); diags.HasErrors() {
return fmt.Errorf("not flat tfvars attributes: %s", diags.Error())
}
return nil
} Prevention
- Treat decode_tfvars input as literal-only `key = value` lines; never include nested blocks.
- If you generate tfvars programmatically, emit attribute assignments only.
- Keep a canonical .tfvars file under test and round-trip it through encode_tfvars/decode_tfvars in CI.
When it happens
Trigger: Calling `decode_tfvars("...")` in an HCL expression where the argument string contains a nested block such as `foo { bar = 1 }`, a duplicate attribute, or a construct HCL accepts as a block. The earlier `hclsyntax.ParseConfig` succeeds (so [121] is not triggered) but `JustAttributes()` rejects the block-shaped body.
Common situations: Feeding a full `.tf` configuration file into `decode_tfvars`; passing JSON/YAML text instead of tfvars syntax; reusing a variable file that mixed attribute and block syntax; copy-pasting an object literal with `{ }` braces rather than `key = value` lines.
Related errors
- invalid expression for variable %q: %s
- Cannot set both 'source' and 'content'
- Must provide one of 'source' or 'content'
- invalid null string in 'scripts'
- invalid empty string in 'scripts'
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/2778a7260d684342.
Report an issue: GitHub.