{"record":{"id":"c2ee41ee8fd074a1","repo":"hashicorp/terraform","slug":"keys-and-searchset-must-be-of-the-same-type","errorCode":null,"errorMessage":"keys and searchset must be of the same type","messagePattern":"keys and searchset must be of the same type","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/lang/funcs/collection.go","lineNumber":352,"sourceCode":"var MatchkeysFunc = function.New(&function.Spec{\n\tParams: []function.Parameter{\n\t\t{\n\t\t\tName: \"values\",\n\t\t\tType: cty.List(cty.DynamicPseudoType),\n\t\t},\n\t\t{\n\t\t\tName: \"keys\",\n\t\t\tType: cty.List(cty.DynamicPseudoType),\n\t\t},\n\t\t{\n\t\t\tName: \"searchset\",\n\t\t\tType: cty.List(cty.DynamicPseudoType),\n\t\t},\n\t},\n\tType: func(args []cty.Value) (cty.Type, error) {\n\t\tty, _ := convert.UnifyUnsafe([]cty.Type{args[1].Type(), args[2].Type()})\n\t\tif ty == cty.NilType {\n\t\t\treturn cty.NilType, errors.New(\"keys and searchset must be of the same type\")\n\t\t}\n\n\t\t// the return type is based on args[0] (values)\n\t\treturn args[0].Type(), nil\n\t},\n\tRefineResult: refineNotNull,\n\tImpl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {\n\t\tif !args[0].IsKnown() {\n\t\t\treturn cty.UnknownVal(cty.List(retType.ElementType())), nil\n\t\t}\n\n\t\tif args[0].LengthInt() != args[1].LengthInt() {\n\t\t\treturn cty.ListValEmpty(retType.ElementType()), errors.New(\"length of keys and values should be equal\")\n\t\t}\n\n\t\toutput := make([]cty.Value, 0)\n\t\tvalues := args[0]\n","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/lang/funcs/collection.go#L334-L370","documentation":"Thrown by the `matchkeys()` function (MatchkeysFunc) in its Type callback when the element types of `keys` (2nd arg) and `searchset` (3rd arg) cannot be unified via convert.UnifyUnsafe. matchkeys joins keys against searchset by equality, so their element types must be compatible; if UnifyUnsafe returns NilType the type check fails before evaluation.","triggerScenarios":"Calling `matchkeys(values, keys, searchset)` where keys and searchset hold different element types, e.g. keys is list(string) and searchset is list(number).","commonSituations":"Building a lookup where keys were typed as strings (e.g. \"1\") but searchset as numbers (1), or vice versa. Inconsistent typing between two data sources joined by matchkeys.","solutions":["Make keys and searchset the same element type, or convertible types (e.g. both list(string)).","Add explicit conversion: `matchkeys(var.values, tolist(var.keys), [tostring(var.target)])`.","Re-type the upstream variables so both sides agree."],"exampleFix":"// before\nlocals { r = matchkeys(var.values, var.keys, [var.target_id]) }  # keys=list(string), target_id=number\n\n// after\nlocals { r = matchkeys(var.values, var.keys, [tostring(var.target_id)]) }","handlingStrategy":"validation","validationCode":"# HCL: unify types before matchkeys\nlocals {\n  keys2      = [for k in var.keys : tostring(k)]\n  searchset2 = [for s in var.searchset : tostring(s)]\n  r = matchkeys(var.values, local.keys2, local.searchset2)\n}","typeGuard":"# HCL: assert same element type\nlocals { ok = length(var.keys) == 0 || try(var.keys[0], null) == try(var.searchset[0], null) }","tryCatchPattern":null,"preventionTips":["Type keys and searchset identically at the variable declaration.","Convert both sides with to{string,number}() before matchkeys.","Validate element-type equality in CI via terraform validate."],"tags":["terraform","hcl","collection-functions","matchkeys","type-unification"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}