TFNFR21 - Discourage Nullability by Default
ID: TFNFR21 - Category: Code Style - Discourage Nullability by Default
nullable = true MUST be avoided.
Variables MUST be declared with nullable = false whenever the variable’s type has a meaningful zero value ({} for objects/maps, [] for lists/sets, "" for strings where empty has the same meaning as absent, etc.). Consumers should signal “no value” by omitting the input, not by explicitly passing null.
Exception — behavior-toggle inputs
A small, well-defined class of inputs MAY keep the implicit nullable = true (i.e. default = null) where null carries a distinct semantic meaning of “no override — use the underlying provider/AVM defaults”, and where representing that state with the type’s zero value would be ambiguous or wrong. Examples include:
var.retryandvar.timeouts(per TFFR7) —nullmeans “do not emit aretry/timeoutsblock; use the AzAPI provider defaults”.var.lock(per the AVM lock interface) —nullmeans “do not create a management lock”.- Optional sub-objects that toggle whole feature blocks on/off, where
{}would be indistinguishable from “feature enabled with all defaults”.
Where this exception applies, the variable MUST:
- Use
default = null(the implicitnullable = trueis permitted only for this purpose). - State explicitly in its
descriptionwhatnullmeans. - Be consumed with a
null-aware pattern (e.g.count = var.lock != null ? 1 : 0, ordynamic "timeouts" { for_each = var.timeouts == null ? [] : [var.timeouts] }).
This exception does not extend to required inputs, to collection-shaped inputs (TFNFR20), or to nested attributes inside an object — those MUST use nullable = false and the type’s zero value.