{"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/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/lang/funcs/collection.go#L175-L211","documentation":"Thrown by the `index()` function (IndexFunc) in its Impl when the first argument's type is neither a list nor a tuple. index() searches an ordered sequence for a value and returns its numeric position, so non-sequence inputs (maps, sets, strings, scalars) are invalid. The check runs before any unknown-value handling.","triggerScenarios":"Calling `index()` with a non-list first argument: `index({a=1,b=2}, 1)`, `index(var.amap, key)`, or `index(\"abc\", \"b\")`. Sets are also rejected because they are unordered.","commonSituations":"Confusing index() (position in list) with lookup() (key in map). Passing a set where ordering is required. Mistyping a variable from list to set during refactor.","solutions":["Ensure the first argument is a list(...) or tuple. Convert with `tolist(...)` if needed.","For key-based access use `lookup()` or `local.map[key]` instead of index().","If the source is a set and order matters, materialize an ordered list."],"exampleFix":"// before\nlocals { i = index(var.tags_map, \"env\") }   # map passed\n\n// after\nlocals { i = index(var.tags_list, \"env\") }   # list(string)","handlingStrategy":"validation","validationCode":"# HCL: check the first arg is a list/tuple\nlocals { i = can(length(var.input)) && try(tolist(var.input), null) != null ? index(var.input, target) : -1 }","typeGuard":"# HCL: convert to list explicitly\nlocals { i = index(tolist(var.input), target) }","tryCatchPattern":null,"preventionTips":["Distinguish index() (list position) from lookup()/map indexing (key).","Declare variables as list(...) not set(...) when order matters.","Add `terraform validate` in CI."],"tags":["terraform","hcl","collection-functions","index","type-check"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}