{"record":{"id":"3aebf8bfe6eaaef7","repo":"hashicorp/terraform","slug":"cannot-decode-tfvars-from-a-null-value","errorCode":null,"errorMessage":"cannot decode tfvars from a null value","messagePattern":"cannot decode tfvars from a null value","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/builtin/providers/terraform/functions.go","lineNumber":99,"sourceCode":"\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\n\t// As usual when we wrap HCL stuff up in functions, we end up needing to\n\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","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/builtin/providers/terraform/functions.go#L81-L117","documentation":"Emitted by decodeTfvarsFunc (functions.go:98-100) when the argument is typed as string but its value is null. Parsing tfvars syntax from a null string is meaningless, so it is rejected explicitly after the type check. The encode counterpart has a symmetric 'cannot encode a null value' check (functions.go:38-42).","triggerScenarios":"Calling decode_tfvars on an optional variable that was not set (resolving to null), e.g. `decode_tfvars(var.optional_tfvars)` where var.optional_tfvars has no default and is unset.","commonSituations":"An optional input variable of type string with no default passed straight to decode_tfvars; a lookup that returns null; nullable module inputs.","solutions":["Provide a default of \"\" (empty string) for the input variable so it is never null: `variable \"x\" { type = string, default = \"\" }`.","Guard with coalesce: `decode_tfvars(coalesce(var.optional_tfvars, \"\"))`.","Skip the decode entirely when the value is null using a conditional."],"exampleFix":"// before\nlocals { out = decode_tfvars(var.maybe_tfvars) }  // null when unset -> error\n\n// after\nvariable \"maybe_tfvars\" { type = string, default = \"\" }\nlocals { out = decode_tfvars(var.maybe_tfvars) }","handlingStrategy":"type-guard","validationCode":"// Reject null before parsing.\nif args[0].IsNull() { return cty.NilVal, errors.New(\"decode_tfvars cannot decode a null string\") }","typeGuard":"// Narrow to a known-non-null string before calling decode_tfvars.\nfunc isNonEmptyString(v cty.Value) bool { return v.Type() == cty.String && v.IsKnown() && !v.IsNull() }","tryCatchPattern":null,"preventionTips":["Give optional input variables a default of \"\" so they never reach decode_tfvars as null.","Guard with coalesce(var.x, \"\") at the call site.","Skip decode entirely when the source is null via a conditional expression.","Constrain variables with type = string to surface type/null issues early."],"tags":["functions","decode-tfvars","null","hcl","optional"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}