hashicorp/terraform · critical
missing field in set: %s.%s
Error message
missing field in set: %s.%s
What it means
A panic in `DiffFieldReader.readSet` (internal/legacy/helper/schema/field_reader_diff.go:214). While reconstructing a set from a diff, the reader iterates diff keys, reads each element via ReadField, and asserts the result `Exists`. If a key it just enumerated does not exist when re-read, it panics 'missing field in set: <key>.<idx>'. The comment notes 'This shouldn't happen because we just verified it does exist' — it is an internal consistency failure of the diff reader's own indexing.
Source
Thrown at internal/legacy/helper/schema/field_reader_diff.go:214
if !strings.HasPrefix(k, prefix) {
continue
}
if strings.HasSuffix(k, "#") {
// Ignore any count field
continue
}
// Split the key, since it might be a sub-object like "idx.field"
parts := strings.Split(k[len(prefix):], ".")
idx := parts[0]
raw, err := r.ReadField(append(address, idx))
if err != nil {
return FieldReadResult{}, err
}
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)
}
// Determine if the set "exists". It exists if there are items or if
// the diff explicitly wanted it empty.
exists := set.Len() > 0
if !exists {
// We could check if the diff value is "0" here but I think the
// existence of "#" on its own is enough to show it existed. This
// protects us in the future from the zero value changing from
// "0" to "" breaking us (if that were to happen).
if _, ok := r.Diff.Attributes[prefix+"#"]; ok {
exists = true
}
}
View on GitHub (pinned to c9def3e214)
Solutions
- Restore state from the most recent `.terraform.tfstate.backup` if state corruption is suspected.
- Re-plan from a clean state to regenerate the diff consistently.
- Ensure the provider version used for apply matches the one used for plan (set hashing must be stable across both).
- Report a provider/Terraform bug if reproduced with matching versions and a fresh plan.
Example fix
null
Defensive patterns
Strategy: validation
Validate before calling
// Go (provider): keep set element hashing stable across plan/apply // Ensure Schema.Hash or nested Elem schema is identical between the version // that planned and the version that applies; add a state migration on change.
Try / catch
// Go: recover from the readSet consistency panic
defer func() {
if r := recover(); r != nil {
res = FieldReadResult{}
err = fmt.Errorf("set field consistency failure: %v; re-apply with a fresh plan", r)
}
}()
res, err = r.readSet(address, schema) Prevention
- Use the same provider version for plan and apply so set hashing does not drift.
- Restore from `.terraform.tfstate.backup` if state corruption is suspected.
- Re-plan from clean state when a set schema changes.
- Add state migrations whenever a nested set's schema/hash changes.
When it happens
Trigger: Applying/reading a diff that contains a set whose element keys were discovered via prefix scan but then resolve to non-existent fields on the nested ReadField call. Typically a symptom of a malformed diff, corrupted state, or a set element whose schema/hash changed between the plan and apply.
Common situations: Set element hashing changed (e.g. a provider altered the hash function / schema of a nested set block) so keys from the diff no longer map to existing fields; corrupted state with dangling set keys; race between concurrent state writes.
Related errors
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/701a743a71f11070.
Report an issue: GitHub.