{"record":{"id":"1368fd7abd8cc4e6","repo":"hashicorp/terraform","slug":"all-arguments-must-have-the-same-type","errorCode":null,"errorMessage":"all arguments must have the same type","messagePattern":"all arguments must have the same type","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/lang/funcs/collection.go","lineNumber":152,"sourceCode":"// stdlib and modified so that it returns the first *non-empty* non-null element\n// from a sequence, instead of merely the first non-null.\nvar CoalesceFunc = function.New(&function.Spec{\n\tParams: []function.Parameter{},\n\tVarParam: &function.Parameter{\n\t\tName:             \"vals\",\n\t\tType:             cty.DynamicPseudoType,\n\t\tAllowUnknown:     true,\n\t\tAllowDynamicType: true,\n\t\tAllowNull:        true,\n\t},\n\tType: func(args []cty.Value) (ret cty.Type, err error) {\n\t\targTypes := make([]cty.Type, len(args))\n\t\tfor i, val := range args {\n\t\t\targTypes[i] = val.Type()\n\t\t}\n\t\tretType, _ := convert.UnifyUnsafe(argTypes)\n\t\tif retType == cty.NilType {\n\t\t\treturn cty.NilType, errors.New(\"all arguments must have the same type\")\n\t\t}\n\t\treturn retType, nil\n\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","sourceCodeStart":134,"sourceCodeEnd":170,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/lang/funcs/collection.go#L134-L170","documentation":"Thrown by CoalesceFunc.Type (the HCL coalesce() builtin). coalesce() must return a single type, so all arguments are passed through convert.UnifyUnsafe; if they cannot be unified it reports that all arguments must share a type.","triggerScenarios":"Mixing types in one call: coalesce(\"a\", 1), coalesce([], {}), coalesce(var.s, var.n) where one is string and one number.","commonSituations":"Coalescing a string default with a numeric value, or two differently-typed optional variables; forgetting that '0' vs 0 differ in type.","solutions":["Normalize each argument to the desired type before calling: coalesce(tostring(var.a), tostring(var.b)).","Pick arguments that are inherently the same type.","Use try() with explicit conversions when types are uncertain."],"exampleFix":"# before\nlocals { name = coalesce(var.display_name, var.id) }   # string vs number\n# after\nlocals { name = coalesce(var.display_name, tostring(var.id)) }","handlingStrategy":"type-guard","validationCode":"# normalize all coalesce args to one type beforehand\nlocals { name = coalesce(tostring(var.a), tostring(var.b)) }","typeGuard":"# guard: unify types before calling coalesce\nlocals {\n  a_str = try(tostring(var.a), null)\n  b_str = try(tostring(var.b), null)\n  name  = coalesce(a_str, b_str)\n}","tryCatchPattern":"locals { name = try(coalesce(tostring(var.a), tostring(var.b)), \"default\") }","preventionTips":["Declare variables with explicit types so coalesce candidates naturally match.","Convert at the source (tostring/tonumber) instead of mixing raw values.","Unit-test locals with sentinel values to catch type drift."],"tags":["hcl","function","coalesce","type-validation"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}