hashicorp/terraform · error

invalid tfvars syntax: %s

Error message

invalid tfvars syntax: %s

What it means

Emitted by decodeTfvarsFunc (functions.go:119-122) when hclsyntax.ParseConfig cannot parse the input string as HCL tfvars syntax. The raw string is parsed at hcl.InitialPos with the label '<decode_tfvars argument>'; any HCL syntax error (unbalanced braces, invalid tokens, bad expression) is flattened into this message because HCL diagnostics cannot be propagated verbatim through the cty function error channel.

Source

Thrown at internal/builtin/providers/terraform/functions.go:121

		// type, since it will be an object type decided based on which
		// arguments and values we find in the string.
		return cty.DynamicVal, nil
	}

	// 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

View on GitHub (pinned to c9def3e214)

Solutions

  1. Read the wrapped HCL diagnostic in %s to locate the exact line/column of the syntax error and fix it.
  2. Validate the .tfvars file standalone with `terraform validate -var-file=...` or by linting it as HCL before feeding it to decode_tfvars.
  3. Ensure the content is HCL tfvars syntax, not JSON — use jsondecode for JSON instead.
  4. Strip BOM and normalize line endings if the string originates from a non-Unix source.

Example fix

// before
locals { out = decode_tfvars("a = [1, 2") }  // unbalanced bracket -> invalid syntax

// after
locals { out = decode_tfvars("a = [1, 2]") }
Defensive patterns

Strategy: validation

Validate before calling

// Validate the string parses as HCL tfvars before relying on decode_tfvars.
f, diags := hclsyntax.ParseConfig([]byte(s), "preflight", hcl.InitialPos)
if diags.HasErrors() {
    return fmt.Errorf("fix tfvars syntax before decode_tfvars: %s", diags.Error())
}

Try / catch

// Surface the HCL diagnostic verbatim so the operator can fix the exact location.
f, hclDiags := hclsyntax.ParseConfig(src, "<decode_tfvars argument>", hcl.InitialPos)
if hclDiags.HasErrors() {
    return cty.NilVal, fmt.Errorf("invalid tfvars syntax: %s", hclDiags.Error())
}

Prevention

When it happens

Trigger: Passing a malformed tfvars string to decode_tfvars: unbalanced braces/brackets, invalid attribute syntax, a stray token, a heredoc or expression the tfvars grammar rejects. Also triggered by content that is valid JSON/another format but not HCL tfvars.

Common situations: Reading a hand-edited .tfvars file with a typo; constructing a tfvars string dynamically with broken concatenation; passing a JSON string (tfvars is HCL, not JSON); Windows line-ending or BOM issues; copy-paste introducing smart quotes.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/b2f382c1720897a2. Report an issue: GitHub.