hashicorp/terraform · error

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

Error message

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

What it means

Raised when an Attribute whose NestedType uses NestingSet transitively contains a WriteOnly attribute. cty hoists WriteOnly marks up to the enclosing set value, so inner per-element WriteOnly flags would be silently lost; only the set-level attribute itself may be WriteOnly. The validator at internal_validate.go:182 calls a.NestedType.ContainsWriteOnly() and rejects the schema.

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 c9def3e214)

Solutions

  1. Switch NestedType.Nesting to NestingList, which permits inner WriteOnly attributes.
  2. Move the WriteOnly flag from the inner attribute to the outer set attribute so the whole set is ephemeral.
  3. Remove WriteOnly if the data is persisted in state.

Example fix

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

// after
"peers": {
    Optional: true,
    NestedType: &Object{
        Nesting: NestingList,
        Attributes: map[string]*Attribute{"token": {Type: cty.String, Optional: true, WriteOnly: true}},
    },
}
Defensive patterns

Strategy: validation

Validate before calling

func assertNestedSetNoWriteOnly(a *configschema.Attribute) error {
    if a.NestedType == nil || a.NestedType.Nesting != configschema.NestingSet { return nil }
    if a.NestedType.ContainsWriteOnly() {
        return fmt.Errorf("NestingSet attribute may not contain WriteOnly attributes")
    }
    return nil
}

Prevention

When it happens

Trigger: An Attribute with NestedType.Nesting == NestingSet where any nested Attribute has WriteOnly: true. The NestingSet branch at line 174 reaches line 182 and ContainsWriteOnly() returns true.

Common situations: Modeling a set of ephemeral credential objects (e.g. a deduped set of API keys) where each element has a WriteOnly secret; converting a NestedType list to a set while keeping inner WriteOnly flags; schema generators marking all secret-looking fields WriteOnly.

Related errors


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