hashicorp/terraform · error
length of keys and values should be equal
Error message
length of keys and values should be equal
What it means
Thrown by MatchkeysFunc.Impl when len(values) != len(keys). matchkeys pairs values[i] with keys[i] by index, so the two lists must be the same length; a mismatch is a logic error.
Source
Thrown at internal/lang/funcs/collection.go:365
},
},
Type: func(args []cty.Value) (cty.Type, error) {
ty, _ := convert.UnifyUnsafe([]cty.Type{args[1].Type(), args[2].Type()})
if ty == cty.NilType {
return cty.NilType, errors.New("keys and searchset must be of the same type")
}
// the return type is based on args[0] (values)
return args[0].Type(), nil
},
RefineResult: refineNotNull,
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
if !args[0].IsKnown() {
return cty.UnknownVal(cty.List(retType.ElementType())), nil
}
if args[0].LengthInt() != args[1].LengthInt() {
return cty.ListValEmpty(retType.ElementType()), errors.New("length of keys and values should be equal")
}
output := make([]cty.Value, 0)
values := args[0]
// Keys and searchset must be the same type.
// We can skip error checking here because we've already verified that
// they can be unified in the Type function
ty, _ := convert.UnifyUnsafe([]cty.Type{args[1].Type(), args[2].Type()})
keys, _ := convert.Convert(args[1], ty)
searchset, _ := convert.Convert(args[2], ty)
// if searchset is empty, return an empty list.
if searchset.LengthInt() == 0 {
return cty.ListValEmpty(retType.ElementType()), nil
}
if !values.IsWhollyKnown() || !keys.IsWhollyKnown() {View on GitHub (pinned to c9def3e214)
Solutions
- Build values and keys together from a single source with a for expression so they stay aligned.
- Add a precondition/guard: assert length(values) == length(keys).
- Re-derive the shorter list from the same iteration as the longer one.
Example fix
# before
locals { m = matchkeys(var.names, var.ids, var.search_ids) } # lengths differ
# after: derive both from one source
locals {
pairs = [for x in var.items : { name = x.name, id = x.id }]
m = matchkeys([for p in local.pairs : p.name], [for p in local.pairs : p.id], var.search_ids)
} Defensive patterns
Strategy: validation
Validate before calling
# assert equal lengths before matchkeys
locals {
ok = length(var.values) == length(var.keys)
r = local.ok ? matchkeys(var.values, var.keys, var.searchset) : []
}
check "align" {
assert {
condition = length(var.values) == length(var.keys)
error_message = "values and keys lists must have equal length"
}
} Try / catch
locals { r = try(matchkeys(var.values, var.keys, var.searchset), []) } Prevention
- Derive parallel lists from one for expression so they cannot drift.
- Add check/precondition blocks asserting length parity.
- Avoid independently filtering two lists that must stay aligned.
When it happens
Trigger: matchkeys(values, keys, searchset) where values and keys were built from different sources or filtered differently, producing unequal lengths.
Common situations: Two parallel lists that got out of sync; one list filtered while the other wasn't; copy-paste using the wrong variable.
Related errors
- no non-null, non-empty-string arguments
- cannot search an empty list
- item not found
- keys and searchset must be of the same type
- input must not contain null list
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/02785d499d6ada09.
Report an issue: GitHub.