hashicorp/terraform · error

no non-null, non-empty-string arguments

Error message

no non-null, non-empty-string arguments

What it means

Thrown by CoalesceFunc.Impl after iterating all arguments: none was non-null and (for strings) non-empty, so there is nothing to return. coalesce() returns the first usable value, and here every candidate was rejected.

Source

Thrown at internal/lang/funcs/collection.go:173

	},
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
		for _, argVal := range args {
			// We already know this will succeed because of the checks in our Type func above
			argVal, _ = convert.Convert(argVal, retType)
			if !argVal.IsKnown() {
				return cty.UnknownVal(retType), nil
			}
			if argVal.IsNull() {
				continue
			}
			if retType == cty.String && argVal.RawEquals(cty.StringVal("")) {
				continue
			}

			return argVal, nil
		}
		return cty.NilVal, errors.New("no non-null, non-empty-string arguments")
	},
})

// IndexFunc constructs a function that finds the element index for a given value in a list.
var IndexFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "list",
			Type: cty.DynamicPseudoType,
		},
		{
			Name: "value",
			Type: cty.DynamicPseudoType,
		},
	},
	Type:         function.StaticReturnType(cty.Number),
	RefineResult: refineNotNull,
	Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {

View on GitHub (pinned to c9def3e214)

Solutions

  1. Add a concrete non-empty fallback as the last argument.
  2. Replace nulls upstream so at least one argument is valid.
  3. Use try() with a hardcoded default if you need guaranteed output.

Example fix

# before
locals { tag = coalesce(var.env_tag, var.default_tag) }   # both null -> error
# after
locals { tag = coalesce(var.env_tag, var.default_tag, "untagged") }
Defensive patterns

Strategy: validation

Validate before calling

# guarantee at least one usable value with a concrete fallback
locals { tag = coalesce(var.a, var.b, "untagged") }

Type guard

# check that at least one candidate is non-empty before coalesce
locals {
  has_value = anytrue([for v in [var.a, var.b] : try(length(tostring(v)) > 0, false)])
  tag       = local.has_value ? coalesce(var.a, var.b) : "untagged"
}

Try / catch

locals { tag = try(coalesce(var.a, var.b), "untagged") }

Prevention

When it happens

Trigger: coalesce(null, null, ""), coalesce(var.optional_a, var.optional_b) when both are unset and default to null/empty, or coalesce() with no arguments.

Common situations: All optional inputs genuinely absent; variables default to null or empty string; chained lookups that all miss.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/b9fd96ba236ed77e. Report an issue: GitHub.