hashicorp/terraform · error

%s%s: NestingGroup blocks cannot be computed

Error message

%s%s: NestingGroup blocks cannot be computed

What it means

Raised when a nested block declared with NestingGroup mode also has Computed=true. NestingGroup is intended to model an always-present feature group whose attributes take default values when the block is omitted; because the group is never null and never user-supplied en bloc, marking it Computed is meaningless and contradicts the semantic contract of the mode. The validator at internal_validate.go:86 rejects this combination so providers cannot construct a self-contradictory schema. Use NestingSingle or an attribute with NestedType if the value truly comes from the provider.

Source

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

		// any nested blocks within a computed block must also be computed
		if b.Computed && !blockS.Computed {
			multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: all nested blocks within computed blocks must also be computed", prefix, name))
		}

		switch blockS.Nesting {
		case NestingSingle:
			switch {
			case blockS.MinItems != blockS.MaxItems:
				multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: MinItems and MaxItems must match in NestingSingle mode", prefix, name))
			case blockS.MinItems < 0 || blockS.MinItems > 1:
				multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: MinItems and MaxItems must be set to either 0 or 1 in NestingSingle mode", prefix, name))
			}
		case NestingGroup:
			if blockS.MinItems != 0 || blockS.MaxItems != 0 {
				multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: MinItems and MaxItems cannot be used in NestingGroup mode", prefix, name))
			}
			if blockS.Computed {
				multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: NestingGroup blocks cannot be computed", prefix, name))
			}
		case NestingList, NestingSet:
			if blockS.MinItems > blockS.MaxItems && blockS.MaxItems != 0 {
				multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: MinItems must be less than or equal to MaxItems in %s mode", prefix, name, blockS.Nesting))
			}
			if blockS.Nesting == NestingSet {
				ety := blockS.Block.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.
					multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: NestingSet blocks may not contain attributes of cty.DynamicPseudoType", prefix, name))
				}
				if blockS.Block.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.
					multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: NestingSet blocks may not contain WriteOnly attributes", prefix, name))

View on GitHub (pinned to c9def3e214)

Solutions

  1. Remove Computed: true from the NestingGroup NestedBlock; the mode already guarantees the block is non-null with defaulted attributes.
  2. If the value must be provider-computed, switch Nesting to NestingSingle (single computed object) or replace the block with an Attribute whose NestedType is an Object.
  3. Search the schema definition for the offending block name and confirm only the intended flags remain after the migration.

Example fix

// before
BlockTypes: map[string]*NestedBlock{
    "settings": {Nesting: NestingGroup, Block: Block{Computed: true, Attributes: ...}},
}

// after
BlockTypes: map[string]*NestedBlock{
    "settings": {Nesting: NestingGroup, Block: Block{Attributes: ...}},
}
Defensive patterns

Strategy: validation

Validate before calling

// before registering the schema, assert NestingGroup blocks are not Computed
func validateGroupBlocks(b *configschema.Block) error {
    for name, nb := range b.BlockTypes {
        if nb == nil { continue }
        if nb.Nesting == configschema.NestingGroup && nb.Computed {
            return fmt.Errorf("%s: NestingGroup cannot be Computed", name)
        }
        if err := validateGroupBlocks(&nb.Block); err != nil { return err }
    }
    return nil
}

Type guard

func isComputedGroup(nb *configschema.NestedBlock) bool {
    return nb != nil && nb.Nesting == configschema.NestingGroup && nb.Computed
}

Prevention

When it happens

Trigger: A provider schema defines a NestedBlock with Nesting: NestingGroup and simultaneously sets Computed: true on the same NestedBlock struct (the embedded Block.Computed field). InternalValidate walks BlockTypes, hits the NestingGroup case at line 81, and emits this error when blockS.Computed is true at line 85.

Common situations: Migrating a block from NestingSingle/NestingList to NestingGroup while leaving an old Computed=true flag set; copying a schema struct verbatim and changing only the Nesting field; modeling a remote API response that is always present but forgetting NestingGroup already guarantees non-null presence.

Related errors


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