hashicorp/terraform · error
cannot decode tfvars from a null value
Error message
cannot decode tfvars from a null value
What it means
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).
Source
Thrown at internal/builtin/providers/terraform/functions.go:99
result := f.Bytes()
return cty.StringVal(string(result)), nil
}
func decodeTfvarsFunc(args []cty.Value) (cty.Value, error) {
// These error checks should not be hit in practice because the language
// runtime should check them before calling, so this is just for robustness
// and completeness.
if len(args) > 1 {
return cty.NilVal, function.NewArgErrorf(1, "too many arguments; only one expected")
}
if len(args) == 0 {
return cty.NilVal, fmt.Errorf("exactly one argument is required")
}
if args[0].Type() != cty.String {
return cty.NilVal, fmt.Errorf("argument must be a string")
}
if args[0].IsNull() {
return cty.NilVal, fmt.Errorf("cannot decode tfvars from a null value")
}
if !args[0].IsKnown() {
// If our input isn't known then we can't even predict the result
// 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-providedView on GitHub (pinned to c9def3e214)
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.
Example fix
// before
locals { out = decode_tfvars(var.maybe_tfvars) } // null when unset -> error
// after
variable "maybe_tfvars" { type = string, default = "" }
locals { out = decode_tfvars(var.maybe_tfvars) } Defensive patterns
Strategy: type-guard
Validate before calling
// Reject null before parsing.
if args[0].IsNull() { return cty.NilVal, errors.New("decode_tfvars cannot decode a null string") } Type guard
// Narrow to a known-non-null string before calling decode_tfvars.
func isNonEmptyString(v cty.Value) bool { return v.Type() == cty.String && v.IsKnown() && !v.IsNull() } Prevention
- 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.
When it happens
Trigger: 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.
Common situations: An optional input variable of type string with no default passed straight to decode_tfvars; a lookup that returns null; nullable module inputs.
Related errors
- argument must be a string
- invalid tfvars syntax: %s
- exactly one argument is required
- invalid tfvars content: %s
- invalid expression for variable %q: %s
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/3aebf8bfe6eaaef7.
Report an issue: GitHub.