{"record":{"id":"711c7911f38a03d3","repo":"hashicorp/terraform","slug":"argument-must-be-a-string","errorCode":null,"errorMessage":"argument must be a string","messagePattern":"argument must be a string","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/builtin/providers/terraform/functions.go","lineNumber":96,"sourceCode":"\t\tbody.SetAttributeValue(key, v)\n\t}\n\n\tresult := f.Bytes()\n\treturn cty.StringVal(string(result)), nil\n}\n\nfunc decodeTfvarsFunc(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\tif args[0].Type() != cty.String {\n\t\treturn cty.NilVal, fmt.Errorf(\"argument must be a string\")\n\t}\n\tif args[0].IsNull() {\n\t\treturn cty.NilVal, fmt.Errorf(\"cannot decode tfvars from a null value\")\n\t}\n\tif !args[0].IsKnown() {\n\t\t// If our input isn't known then we can't even predict the result\n\t\t// type, since it will be an object type decided based on which\n\t\t// arguments and values we find in the string.\n\t\treturn cty.DynamicVal, nil\n\t}\n\n\t// If we get here then we know that:\n\t// - there's exactly one element in args\n\t// - it's a string\n\t// - it is known and non-null\n\t// So therefore the following is guaranteed to succeed.\n\tsrc := []byte(args[0].AsString())\n","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/builtin/providers/terraform/functions.go#L78-L114","documentation":"Emitted by decodeTfvarsFunc (functions.go:95-97) when the single argument's cty type is not cty.String. decode_tfvars parses HCL tfvars syntax from a string; a non-string value (number, list, object, bool) cannot be parsed and is rejected after the arity check but before null/known checks.","triggerScenarios":"Calling decode_tfvars with a number, boolean, list, or object instead of a string, e.g. `decode_tfvars(42)` or `decode_tfvars({a=1})`. The schema declares the parameter as String, so the runtime normally type-coerces or rejects first; this is the defensive fallback.","commonSituations":"Forgetting to wrap the input in a string; passing a variable of the wrong type; a programmatic caller passing a non-string cty.Value that bypassed schema type enforcement.","solutions":["Ensure the argument is a string, e.g. `decode_tfvars(var.tfvars_string)` or `decode_tfvars(file(\"terraform.tfvars\"))` (file() returns a string).","Add a type constraint `type = string` to the input variable feeding decode_tfvars.","If the source is JSON, convert with `jsondecode` only after decoding tfvars, not before."],"exampleFix":"// before\nlocals { out = decode_tfvars(filesize) }  // filesize is a number\n\n// after\nlocals { out = decode_tfvars(file(\"terraform.tfvars\")) }","handlingStrategy":"type-guard","validationCode":"// Type-check the argument before parsing.\nif args[0].Type() != cty.String {\n    return cty.NilVal, fmt.Errorf(\"decode_tfvars argument must be string, got %s\", args[0].Type().FriendlyName())\n}","typeGuard":"// Narrow to a known-non-null string before calling decode_tfvars.\nfunc isCtyString(v cty.Value) bool { return v.Type() == cty.String && !v.IsNull() && v.IsKnown() }","tryCatchPattern":null,"preventionTips":["Use file() (which returns string) or a type=string variable to feed decode_tfvars.","Add `type = string` constraints to source variables so the runtime rejects mismatches early.","Do not pass numbers/objects/lists; convert with tostring() only when meaningful.","Remember tfvars is HCL, not JSON — use jsondecode for JSON inputs separately."],"tags":["functions","decode-tfvars","type-validation","hcl"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}