{"record":{"id":"b9fd96ba236ed77e","repo":"hashicorp/terraform","slug":"no-non-null-non-empty-string-arguments","errorCode":null,"errorMessage":"no non-null, non-empty-string arguments","messagePattern":"no non-null, non-empty-string arguments","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/lang/funcs/collection.go","lineNumber":173,"sourceCode":"\t},\n\tRefineResult: refineNotNull,\n\tImpl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {\n\t\tfor _, argVal := range args {\n\t\t\t// We already know this will succeed because of the checks in our Type func above\n\t\t\targVal, _ = convert.Convert(argVal, retType)\n\t\t\tif !argVal.IsKnown() {\n\t\t\t\treturn cty.UnknownVal(retType), nil\n\t\t\t}\n\t\t\tif argVal.IsNull() {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tif retType == cty.String && argVal.RawEquals(cty.StringVal(\"\")) {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\treturn argVal, nil\n\t\t}\n\t\treturn cty.NilVal, errors.New(\"no non-null, non-empty-string arguments\")\n\t},\n})\n\n// IndexFunc constructs a function that finds the element index for a given value in a list.\nvar IndexFunc = function.New(&function.Spec{\n\tParams: []function.Parameter{\n\t\t{\n\t\t\tName: \"list\",\n\t\t\tType: cty.DynamicPseudoType,\n\t\t},\n\t\t{\n\t\t\tName: \"value\",\n\t\t\tType: cty.DynamicPseudoType,\n\t\t},\n\t},\n\tType:         function.StaticReturnType(cty.Number),\n\tRefineResult: refineNotNull,\n\tImpl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/lang/funcs/collection.go#L155-L191","documentation":"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.","triggerScenarios":"coalesce(null, null, \"\"), coalesce(var.optional_a, var.optional_b) when both are unset and default to null/empty, or coalesce() with no arguments.","commonSituations":"All optional inputs genuinely absent; variables default to null or empty string; chained lookups that all miss.","solutions":["Add a concrete non-empty fallback as the last argument.","Replace nulls upstream so at least one argument is valid.","Use try() with a hardcoded default if you need guaranteed output."],"exampleFix":"# before\nlocals { tag = coalesce(var.env_tag, var.default_tag) }   # both null -> error\n# after\nlocals { tag = coalesce(var.env_tag, var.default_tag, \"untagged\") }","handlingStrategy":"validation","validationCode":"# guarantee at least one usable value with a concrete fallback\nlocals { tag = coalesce(var.a, var.b, \"untagged\") }","typeGuard":"# check that at least one candidate is non-empty before coalesce\nlocals {\n  has_value = anytrue([for v in [var.a, var.b] : try(length(tostring(v)) > 0, false)])\n  tag       = local.has_value ? coalesce(var.a, var.b) : \"untagged\"\n}","tryCatchPattern":"locals { tag = try(coalesce(var.a, var.b), \"untagged\") }","preventionTips":["Always end coalesce chains with a literal default.","Default optional variables to a real value, not null/empty.","Use precondition checks to fail fast with a clear message when all inputs are empty."],"tags":["hcl","function","coalesce","validation"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T20:17:04.800Z"}