hashicorp/terraform · error

lookup failed to find key %s

Error message

lookup failed to find key %s

What it means

Returned by the lookup built-in's Impl (LookupFunc, internal/lang/funcs/collection.go:326) when the requested key is absent from the map/object and no default value (third argument) was supplied. After unmarking and confirming both map and key are known, the function checks HasAttribute (objects) / HasIndex (maps); on miss with no default set it returns cty.UnknownVal(DynamicPseudoType) plus this error, with the key redacted if it carries sensitive marks.

Source

Thrown at internal/lang/funcs/collection.go:326

		lookupKey := keyVal.AsString()

		if mapVar.Type().IsObjectType() {
			if mapVar.Type().HasAttribute(lookupKey) {
				return mapVar.GetAttr(lookupKey).WithMarks(markses...), nil
			}
		} else if mapVar.HasIndex(cty.StringVal(lookupKey)) == cty.True {
			return mapVar.Index(cty.StringVal(lookupKey)).WithMarks(markses...), nil
		}

		if defaultValueSet {
			defaultVal, err = convert.Convert(defaultVal, retType)
			if err != nil {
				return cty.NilVal, err
			}
			return defaultVal.WithMarks(markses...), nil
		}

		return cty.UnknownVal(cty.DynamicPseudoType), fmt.Errorf(
			"lookup failed to find key %s", redactIfSensitive(lookupKey, keyMarks))
	},
})

// MatchkeysFunc constructs a function that constructs a new list by taking a
// subset of elements from one list whose indexes match the corresponding
// indexes of values in another list.
var MatchkeysFunc = function.New(&function.Spec{
	Params: []function.Parameter{
		{
			Name: "values",
			Type: cty.List(cty.DynamicPseudoType),
		},
		{
			Name: "keys",
			Type: cty.List(cty.DynamicPseudoType),
		},
		{

View on GitHub (pinned to c9def3e214)

Solutions

  1. Supply a default: lookup(var.some_map, "missing_key", "fallback").
  2. Use try() to fall back gracefully: try(var.some_map.missing_key, "fallback").
  3. Verify the key exists with contains(keys(var.some_map), "missing_key") before lookup.
  4. Populate the map upstream so the expected key is always present.

Example fix

# before (HCL)
v = lookup(var.tags, "env")  # tags has no "env" -> lookup failed to find key "env"

# after
v = lookup(var.tags, "env", "default")
# or
v = try(var.tags.env, "default")
# or guard:
v = contains(keys(var.tags), "env") ? lookup(var.tags, "env") : "default
Defensive patterns

Strategy: fallback

Validate before calling

# (HCL) check existence before lookup
locals {
  has_key = contains(keys(var.tags), "env")
  v       = local.has_key ? lookup(var.tags, "env") : "default"
}

Type guard

# (HCL) type-ish guard using contains
locals {
  key_present = contains(keys(var.tags), "env")
}

Try / catch

# (HCL) always supply a default, or use try()
value = lookup(var.tags, "env", "default")
# or
value = try(var.tags.env, "default")

Prevention

When it happens

Trigger: Calling lookup(var.some_map, "missing_key") where 'missing_key' is not present and no third default argument is given; both map and key are fully known so lookup falls through to the not-found path.

Common situations: Referencing a tag/label key that doesn't exist in the map, environment-specific maps missing a key in some workspaces, typo'd keys, or assuming a key exists when the source only populates it conditionally.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/6cd297cf2ecf08a7. Report an issue: GitHub.