hashicorp/terraform · critical

missing field in set: %s.%s

Error message

missing field in set: %s.%s

What it means

Panics inside MapFieldReader.readSet (internal/legacy/helper/schema/field_reader_map.go:154) while reconstructing a TypeSet from a flatmap. After a set-element key (e.g. "ports.0") is observed in the underlying Map, the reader re-reads that exact sub-address via ReadField and asserts Exists==true; the comment admits 'this shouldn't happen because we just verified it does exist'. When the re-read returns false the internal invariant is broken and the process panics.

Source

Thrown at internal/legacy/helper/schema/field_reader_map.go:154

			return true
		}
		if strings.HasPrefix(k, prefix+"#") {
			// Ignore the count field
			return true
		}

		// Split the key, since it might be a sub-object like "idx.field"
		parts := strings.Split(k[len(prefix):], ".")
		idx := parts[0]

		var raw FieldReadResult
		raw, err = r.ReadField(append(address, idx))
		if err != nil {
			return false
		}
		if !raw.Exists {
			// This shouldn't happen because we just verified it does exist
			panic("missing field in set: " + k + "." + idx)
		}

		set.Add(raw.Value)

		// Due to the way multimap readers work, if we've seen the number
		// of fields we expect, then exit so that we don't read later values.
		// For example: the "set" map might have "ports.#", "ports.0", and
		// "ports.1", but the "state" map might have those plus "ports.2".
		// We don't want "ports.2"
		countActual[idx] = struct{}{}
		if len(countActual) >= countExpected {
			return false
		}

		return true
	})
	if !completed && err != nil {
		return FieldReadResult{}, err

View on GitHub (pinned to c9def3e214)

Solutions

  1. Read the panic message: it prints the offending 'k.idx'; inspect that flatmap key in the state to see why its nested fields are unreadable.
  2. If you supply a custom MapReader, make Access(k) and Range agree exactly (a key visited by Range must be retrievable by Access).
  3. For real state corruption, restore from a known-good backup or run `terraform refresh`/`terraform apply -refresh-only` against a clean state.
  4. Reproduce in a unit test with TestResourceData to isolate which schema/Elem shape causes the re-read miss, then fix the schema.

Example fix

// before: custom MapReader whose Access/Range disagree
type Bad struct{ m map[string]string }
func (b Bad) Access(k string) (string,bool){ return "", false } // never resolves
func (b Bad) Range(f func(string,string) bool) bool { for k,v := range b.m { if !f(k,v){return false} }; return true }
// after: Access and Range are consistent
func (b Bad) Access(k string) (string,bool){ v,ok := b.m[k]; return v,ok }
Defensive patterns

Strategy: validation

Validate before calling

// before calling Setok on a set reconstructed from a flatmap, ensure each
// set element key is resolvable by the same MapReader that produced it.
func flatmapSetConsistent(m schema.MapReader, prefix string) error {
    bad := []string{}
    m.Range(func(k, _ string) bool {
        if strings.HasPrefix(k, prefix) && !strings.HasSuffix(k, ".#") {
            if _, ok := m.Access(k); !ok { bad = append(bad, k) }
        }
        return true
    })
    if len(bad) > 0 { return fmt.Errorf("unresolvable set keys: %v", bad) }
    return nil
}

Try / catch

// last-resort: recover from the internal panic at a provider boundary
defer func() {
    if r := recover(); r != nil {
        log.Printf("[ERROR] schema readSet panic: %v", r)
    }
}()

Prevention

When it happens

Trigger: A flatmap or MultiMapReader state where a set element key is present (matches the set prefix and is not the count field) but its nested fields cannot be resolved by addrToSchema during the recursive ReadField. Common with a MultiMapReader layered over a dirty/partial state, or any custom MapReader whose Range and Access disagree.

Common situations: Corrupted or hand-edited state files, custom providers shimming legacy state, state upgrades where set element schemas changed between versions, and provider unit tests feeding hand-crafted flatmaps.

Related errors


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