hashicorp/terraform · error
lookup() takes two or three arguments, got
Error message
lookup() takes two or three arguments, got %d
What it means
lookup() type-check error: the HCL lookup() function accepts exactly two mandatory arguments (map, key) plus an optional third (default). The function's Type callback rejects arg counts outside [1,3] -- but note the message says 'two or three arguments, got N' while the actual gate is len(args) < 1 || len(args) > 3, so it triggers on 0 args or >3 args (the message wording reflects the expected end-user signature, not the raw check).
Solutions
- Use exactly lookup(map, key) or lookup(map, key, default).
- Remove extra positional arguments; if multiple defaults are needed, combine them with coalesce inside the default slot.
Example fix
// before val = lookup(var.map, "k", var.def1, var.def2) // after val = lookup(var.map, "k", coalesce(var.def1, var.def2))
Defensive patterns
Strategy: validation
Validate before calling
// Use exactly the supported arity.
locals { v = length([var.map, var.key]) == 2 ? lookup(var.map, var.key) : lookup(var.map, var.key, var.default) } Prevention
- Limit lookup() to 2 or 3 arguments.
- Combine multiple defaults with coalesce inside the third arg.
- Run terraform validate early to catch arity errors.
When it happens
Trigger: Calling lookup() with zero arguments, or with more than three arguments (e.g. lookup(map, key, default1, default2)). The VarParam absorbs extras only up to the internal cap of 3.
Common situations: Wrong number of trailing commas, a splat/for-expression that produced too many positional args, copy-paste adding an extra default value.
Related errors
- lookup failed to find key
- invalid CIDR expression
- at most 1 action can be invoked per operation
- can't compute sum of opposing infinities
- can't delete default state
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/a71e12435e1ae6dc.
Report an issue: GitHub.
Appendix: source
Thrown at internal/lang/funcs/collection.go:248
},
{
Name: "key",
Type: cty.String,
AllowMarked: true,
AllowUnknown: true,
},
},
VarParam: &function.Parameter{
Name: "default",
Type: cty.DynamicPseudoType,
AllowUnknown: true,
AllowDynamicType: true,
AllowNull: true,
AllowMarked: true,
},
Type: func(args []cty.Value) (ret cty.Type, err error) {
if len(args) < 1 || len(args) > 3 {
return cty.NilType, fmt.Errorf("lookup() takes two or three arguments, got %d", len(args))
}
ty := args[0].Type()
switch {
case ty.IsObjectType():
if !args[1].IsKnown() {
return cty.DynamicPseudoType, nil
}
keyVal, _ := args[1].Unmark()
key := keyVal.AsString()
if ty.HasAttribute(key) {
return args[0].GetAttr(key).Type(), nil
} else if len(args) == 3 {
// if the key isn't found but a default is provided,
// return the default type
return args[2].Type(), nilView on GitHub (pinned to d32a084675)