hashicorp/terraform · error
argument must be a list or tuple
Error message
argument must be a list or tuple
What it means
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.
Source
Thrown at internal/lang/funcs/collection.go:193
})
// IndexFunc constructs a function that finds the element index for a given value in a list.
var IndexFunc = function.New(&function.Spec{
Params: []function.Parameter{
{
Name: "list",
Type: cty.DynamicPseudoType,
},
{
Name: "value",
Type: cty.DynamicPseudoType,
},
},
Type: function.StaticReturnType(cty.Number),
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
if !(args[0].Type().IsListType() || args[0].Type().IsTupleType()) {
return cty.NilVal, errors.New("argument must be a list or tuple")
}
if !args[0].IsKnown() {
return cty.UnknownVal(cty.Number), nil
}
if args[0].LengthInt() == 0 { // Easy path
return cty.NilVal, errors.New("cannot search an empty list")
}
for it := args[0].ElementIterator(); it.Next(); {
i, v := it.Element()
eq, err := stdlib.Equal(v, args[1])
if err != nil {
return cty.NilVal, err
}
if !eq.IsKnown() {
return cty.UnknownVal(cty.Number), nilView on GitHub (pinned to c9def3e214)
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.
Example fix
# before
locals { i = index(var.tags_set, "prod") } # set -> error
# after
locals { i = index(tolist(var.tags_set), "prod") }
# for a map, use lookup instead:
locals { v = lookup(var.colors, "red", "none") } Defensive patterns
Strategy: type-guard
Validate before calling
# ensure first arg is a list/tuple before index()
locals {
ok = can(index(tolist(var.x), "y"))
res = local.ok ? index(tolist(var.x), "y") : -1
} Type guard
# normalize sets to lists; redirect maps to lookup()
locals {
i = length(var.x) >= 0 ? index(tolist(var.x), "y") : -1
v = lookup(var.m, "k", "none")
} Try / catch
locals { i = try(index(tolist(var.x), "y"), -1) } Prevention
- 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.
When it happens
Trigger: index("abc", "b") (a string), index({a=1}, "a") (a map/object), index(toset([...]), x) (a set).
Common situations: Confusing index() with map lookup; passing a set (unordered, so index is meaningless); assuming index() works on strings like Python.
Related errors
- argument must be a string, a collection type, or a structura
- all arguments must have the same type
- cannot search an empty list
- item not found
- keys and searchset must be of the same type
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/65449b70a249ae3c.
Report an issue: GitHub.