{"record":{"id":"65449b70a249ae3c","repo":"hashicorp/terraform","slug":"argument-must-be-a-list-or-tuple","errorCode":null,"errorMessage":"argument must be a list or tuple","messagePattern":"argument must be a list or tuple","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/lang/funcs/collection.go","lineNumber":193,"sourceCode":"})\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) {\n\t\tif !(args[0].Type().IsListType() || args[0].Type().IsTupleType()) {\n\t\t\treturn cty.NilVal, errors.New(\"argument must be a list or tuple\")\n\t\t}\n\n\t\tif !args[0].IsKnown() {\n\t\t\treturn cty.UnknownVal(cty.Number), nil\n\t\t}\n\n\t\tif args[0].LengthInt() == 0 { // Easy path\n\t\t\treturn cty.NilVal, errors.New(\"cannot search an empty list\")\n\t\t}\n\n\t\tfor it := args[0].ElementIterator(); it.Next(); {\n\t\t\ti, v := it.Element()\n\t\t\teq, err := stdlib.Equal(v, args[1])\n\t\t\tif err != nil {\n\t\t\t\treturn cty.NilVal, err\n\t\t\t}\n\t\t\tif !eq.IsKnown() {\n\t\t\t\treturn cty.UnknownVal(cty.Number), nil","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/lang/funcs/collection.go#L175-L211","documentation":"Thrown by IndexFunc.Impl (the HCL index() builtin) when the first argument's type is neither a list nor a tuple. index() only searches ordered list/tuple collections for a value.","triggerScenarios":"index(\"abc\", \"b\") (a string), index({a=1}, \"a\") (a map/object), index(toset([...]), x) (a set).","commonSituations":"Confusing index() with map lookup; passing a set (unordered, so index is meaningless); assuming index() works on strings like Python.","solutions":["Use lookup() or direct .attr / map[key] access for maps/objects.","Convert sets to lists: index(tolist(var.set), value).","Use strindex/regex for substring position in a string."],"exampleFix":"# before\nlocals { i = index(var.tags_set, \"prod\") }   # set -> error\n# after\nlocals { i = index(tolist(var.tags_set), \"prod\") }\n# for a map, use lookup instead:\nlocals { v = lookup(var.colors, \"red\", \"none\") }","handlingStrategy":"type-guard","validationCode":"# ensure first arg is a list/tuple before index()\nlocals {\n  ok  = can(index(tolist(var.x), \"y\"))\n  res = local.ok ? index(tolist(var.x), \"y\") : -1\n}","typeGuard":"# normalize sets to lists; redirect maps to lookup()\nlocals {\n  i = length(var.x) >= 0 ? index(tolist(var.x), \"y\") : -1\n  v = lookup(var.m, \"k\", \"none\")\n}","tryCatchPattern":"locals { i = try(index(tolist(var.x), \"y\"), -1) }","preventionTips":["Use lookup() for maps/objects, not index().","Wrap sets with tolist() before positional search.","Type variables as list(...) rather than set(...) when you need index semantics."],"tags":["hcl","function","index","type-validation"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}