hashicorp/terraform · error
cannot decode tfvars from a null value
Error message
cannot decode tfvars from a null value
What it means
decode_tfvars refuses to parse a null input because there is no tfvars content to decode. The function's declared parameter type is non-nullable cty.String, so reaching this branch means the language runtime failed to enforce the schema. It is a defensive guard, not a normal user-facing path.
Solutions
- Ensure the caller honors the function schema (Parameter Type=cty.String, no AllowNull) so null never reaches the function
- Coalesce the input before calling: decode_tfvars(coalesce(var.maybe_null, ""))
- If invoking from Go, guard args[0].IsNull() (and args[0].IsKnown()) before calling decodeTfvarsFunc
Example fix
// before decode_tfvars(var.maybe_null) // after decode_tfvars(coalesce(var.maybe_null, ""))
Defensive patterns
Strategy: validation
Validate before calling
// In Go, before invoking decodeTfvarsFunc directly:
if len(args) != 1 || args[0].IsNull() || !args[0].IsKnown() || args[0].Type() != cty.String {
return cty.NilVal, fmt.Errorf("decode_tfvars requires one known, non-null string")
}
// In HCL, ensure a non-null input before the call:
// decode_tfvars(coalesce(var.maybe_null, "")) Type guard
// HCL-level guard: guarantee a non-null string reaches decode_tfvars
locals {
safe_src = var.maybe_null == null ? "" : var.maybe_null
}
// then: decode_tfvars(local.safe_src) Prevention
- Treat decode_tfvars as taking a non-nullable string and coalesce upstream
- When calling the Go func directly, replicate the runtime's schema checks (type, null, known-ness, arity)
- Write a unit test that passes cty.NullVal(cty.String) to confirm your guard fires before the provider error
When it happens
Trigger: Calling decode_tfvars(null) or decode_tfvars(var.x) where var.x resolves to null and the runtime did not short-circuit; invoking decodeTfvarsFunc directly from Go with cty.NullVal(cty.String) as args[0].
Common situations: A Terraform Core / plugin dispatch bug that ignores the function's parameter schema; direct unit tests calling the Go function with a null cty.Value instead of routing through the runtime.
Related errors
- tags must be a set or object, not
- invalid expression for variable
- invalid tfvars content
- invalid tfvars syntax
- a network issue prevented cloud configuration;
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/3aebf8bfe6eaaef7.
Report an issue: GitHub.
Appendix: 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 d32a084675)