{"record":{"id":"7c37c8c83d0fc61a","repo":"hashicorp/terraform","slug":"invalid-expression-for-variable-q-s","errorCode":null,"errorMessage":"invalid expression for variable %q: %s","messagePattern":"invalid expression for variable %q: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/builtin/providers/terraform/functions.go","lineNumber":134,"sourceCode":"\t// stuff HCL diagnostics into plain string error messages. This produces\n\t// a non-ideal result but is still better than hiding the HCL-provided\n\t// diagnosis altogether.\n\tf, hclDiags := hclsyntax.ParseConfig(src, \"<decode_tfvars argument>\", hcl.InitialPos)\n\tif hclDiags.HasErrors() {\n\t\treturn cty.NilVal, fmt.Errorf(\"invalid tfvars syntax: %s\", hclDiags.Error())\n\t}\n\tattrs, hclDiags := f.Body.JustAttributes()\n\tif hclDiags.HasErrors() {\n\t\treturn cty.NilVal, fmt.Errorf(\"invalid tfvars content: %s\", hclDiags.Error())\n\t}\n\tretAttrs := make(map[string]cty.Value, len(attrs))\n\tfor name, attr := range attrs {\n\t\t// Evaluating the expression with no EvalContext achieves the same\n\t\t// interpretation as Terraform CLI makes of .tfvars files, rejecting\n\t\t// any function calls or references to symbols.\n\t\tv, hclDiags := attr.Expr.Value(nil)\n\t\tif hclDiags.HasErrors() {\n\t\t\treturn cty.NilVal, fmt.Errorf(\"invalid expression for variable %q: %s\", name, hclDiags.Error())\n\t\t}\n\t\tretAttrs[name] = v\n\t}\n\n\treturn cty.ObjectVal(retAttrs), nil\n}\n\nfunc encodeExprFunc(args []cty.Value) (cty.Value, error) {\n\t// These error checks should not be hit in practice because the language\n\t// runtime should check them before calling, so this is just for robustness\n\t// and completeness.\n\tif len(args) > 1 {\n\t\treturn cty.NilVal, function.NewArgErrorf(1, \"too many arguments; only one expected\")\n\t}\n\tif len(args) == 0 {\n\t\treturn cty.NilVal, fmt.Errorf(\"exactly one argument is required\")\n\t}\n","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/builtin/providers/terraform/functions.go#L116-L152","documentation":"Thrown by `decode_tfvars` (functions.go:134) when a top-level attribute parses but its expression cannot be evaluated with a nil EvalContext. Because `decode_tfvars` evaluates each attribute with no evaluation context, any function call, variable reference, or unknown symbol makes `attr.Expr.Value(nil)` fail, and the attribute name plus the HCL diagnostic are returned.","triggerScenarios":"The tfvars string contains a function call such as `name = upper(\"x\")`, a reference such as `name = var.region`, or any identifier that is not a literal. These are legal in normal `.tfvars` evaluation against a configured root module but are rejected here because `decode_tfvars` is a pure literal parser.","commonSituations":"Authoring tfvars that rely on interpolation and expecting `decode_tfvars` to resolve them; round-tripping an object that included function calls; feeding tfvars produced by tooling that emits references.","solutions":["Replace every function call or reference with its already-computed literal value before passing the string to `decode_tfvars`.","If you need evaluated tfvars, load the file normally via the root module's variable declarations instead of through `decode_tfvars`.","Use `encode_tfvars`/`encode_expr` to produce literal-only strings you can safely round-trip back.","Scan the source for `(` , `[a-z].*\\.` references in a pre-check (see defense) to fail fast."],"exampleFix":"// before\ndecode_tfvars(\"region = upper(var.region)\")\n\n// after\ndecode_tfvars(\"region = \"US-EAST-1\"\")","handlingStrategy":"try-catch","validationCode":"// Heuristic pre-check: reject obvious function calls and references.\nvar exprish = regexp.MustCompile(`(?m)^\\s*[A-Za-z_][\\w.-]*\\s*=\\s*[A-Za-z_][\\w]*\\s*\\(`)\nfunc hasLikelyCallOrRef(src string) bool { return exprish.MatchString(src) }","typeGuard":null,"tryCatchPattern":"val, err := provider.CallFunction(providers.CallFunctionRequest{\n    FunctionName: \"decode_tfvars\",\n    Arguments:    []cty.Value{cty.StringVal(raw)},\n})\nif err != nil {\n    // attribute-level parse failure; surface err to the user verbatim,\n    // it already names the offending variable.\n    return fmt.Errorf(\"decode_tfvars rejected input: %w\", err)\n}","preventionTips":["Only ever put literal values (strings, numbers, bools, lists, maps) in strings fed to decode_tfvars.","Pre-evaluate any interpolation before constructing the tfvars string.","When round-tripping objects, prefer encode_tfvars so the output is guaranteed literal-only."],"tags":["terraform","hcl","decode-tfvars","built-in-function","expression","user-input"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}