hashicorp/terraform · error

: NestingSet attributes may not contain WriteOnly attributes

Error message

%s%s: NestingSet attributes may not contain WriteOnly attributes

What it means

Thrown during schema validation when a NestingSet block contains an attribute marked WriteOnly. The runtime marks WriteOnly values and those marks get hoisted up to the enclosing set, which would corrupt set identity for the whole collection. To keep set semantics well-defined, only the set itself may be WriteOnly, never any nested attribute inside it.

Solutions

  1. Remove WriteOnly: true from every attribute that lives inside the NestingSet block, or
  2. Move the WriteOnly attribute out of the set onto a sibling attribute on the parent block, or
  3. Change the nesting from NestingSet to NestingList/NestingMap, which do not have the mark-hoisting constraint.
  4. If the entire set is meant to be write-only, mark the parent Attribute (not its children) accordingly.

Example fix

// before
NestedType: &configschema.Object{
    Nesting: configschema.NestingSet,
    Attributes: map[string]*configschema.Attribute{
        "token": {Type: cty.String, Optional: true, WriteOnly: true},
    },
}

// after — move WriteOnly out of the set
NestedType: &configschema.Object{
    Nesting: configschema.NestingList,
    Attributes: map[string]*configschema.Attribute{
        "token": {Type: cty.String, Optional: true, WriteOnly: true},
    },
}
Defensive patterns

Strategy: validation

Validate before calling

func assertSetHasNoWriteOnly(o *configschema.Object) error {
    if o == nil || o.Nesting != configschema.NestingSet { return nil }
    if o.ContainsWriteOnly() {
        return fmt.Errorf("NestingSet object contains WriteOnly attributes")
    }
    return nil
}

Type guard

func isWriteOnlySafe(o *configschema.Object) bool {
    if o == nil { return true }
    if o.Nesting == configschema.NestingSet && o.ContainsWriteOnly() { return false }
    for _, a := range o.Attributes {
        if a != nil && a.NestedType != nil && !isWriteOnlySafe(a.NestedType) { return false }
    }
    return true
}

Prevention

When it happens

Trigger: Declaring an attribute with WriteOnly: true inside a NestedType whose Nesting is NestingSet, then calling InternalValidate. WriteOnly attributes (ephemeral/sensitive-on-write values) are a newer schema feature used to model values that must not persist in state.

Common situations: Adding ephemeral credentials or tokens to a set-typed block; converting a sensitive attribute into a WriteOnly one without checking whether it lives inside a set; provider framework migrations that introduce WriteOnly on pre-existing set members.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/9ac692b1c70528f5. Report an issue: GitHub.

Appendix: source

Thrown at internal/configs/configschema/internal_validate.go:186

	if a.NestedType != nil {
		switch a.NestedType.Nesting {
		case NestingSingle, NestingMap, NestingGroup:
			// no validations to perform
		case NestingList, NestingSet:
			if a.NestedType.Nesting == NestingSet {
				ety := a.ImpliedType()
				if ety.HasDynamicTypes() {
					// This is not permitted because the HCL (cty) set implementation
					// needs to know the exact type of set elements in order to
					// properly hash them, and so can't support mixed types.
					err = errors.Join(err, fmt.Errorf("%s%s: NestingSet attributes may not contain attributes of cty.DynamicPseudoType", prefix, name))
				}
				if a.NestedType.ContainsWriteOnly() {
					// This is not permitted because any marks within sets will
					// be hoisted up the outer set value, so only the set itself
					// can be WriteOnly.
					err = errors.Join(err, fmt.Errorf("%s%s: NestingSet attributes may not contain WriteOnly attributes", prefix, name))
				}
			}
		default:
			err = errors.Join(err, fmt.Errorf("%s%s: invalid nesting mode %s", prefix, name, a.NestedType.Nesting))
		}
		for name, attrS := range a.NestedType.Attributes {
			if attrS == nil {
				err = errors.Join(err, fmt.Errorf("%s%s: attribute schema is nil", prefix, name))
				continue
			}
			err = errors.Join(err, attrS.internalValidate(name, prefix))
		}
	}

	return err
}

func (o *Object) InternalValidate() error {

View on GitHub (pinned to d32a084675)