hashicorp/terraform · error

%s%s: all attributes within computed blocks must also be com

Error message

%s%s: all attributes within computed blocks must also be computed

What it means

When a Block has Computed=true, every Attribute inside it must also be Computed (checked at lines 44-46), because a provider-supplied (computed) block cannot contain user-mutable fields. The validator iterates each attribute and appends this error if attrS.Computed is false while the parent block is computed.

Source

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

}

func (b *Block) internalValidate(prefix string) error {
	var multiErr error

	if prefix == "" && !b.Deprecated && b.DeprecationMessage != "" {
		multiErr = errors.Join(multiErr, fmt.Errorf("top-level block: DeprecationMessage must not be set when Deprecated is false"))
	}

	for name, attrS := range b.Attributes {
		if attrS == nil {
			multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: attribute schema is nil", prefix, name))
			continue
		}
		multiErr = errors.Join(multiErr, attrS.internalValidate(name, prefix))

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

	for name, blockS := range b.BlockTypes {
		if blockS == nil {
			multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: block schema is nil", prefix, name))
			continue
		}

		if _, isAttr := b.Attributes[name]; isAttr {
			multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: name defined as both attribute and child block type", prefix, name))
		} else if !validName.MatchString(name) {
			multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: name may contain only lowercase letters, digits and underscores", prefix, name))
		}
		if !blockS.Deprecated && blockS.DeprecationMessage != "" {
			multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: DeprecationMessage must not be set when Deprecated is false", prefix, name))
		}

View on GitHub (pinned to c9def3e214)

Solutions

  1. Set Computed = true on every attribute inside the computed block.
  2. If the attribute is genuinely user-settable, the parent block must not be Computed - move it out or drop Computed on the block.

Example fix

// before
&configschema.Block{
    Computed: true,
    Attributes: map[string]*configschema.Attribute{
        "id":   {Type: cty.String, Computed: true},
        "name": {Type: cty.String, Optional: true},  // illegal under Computed block
    },
}

// after
&configschema.Block{
    Computed: true,
    Attributes: map[string]*configschema.Attribute{
        "id":   {Type: cty.String, Computed: true},
        "name": {Type: cty.String, Computed: true},
    },
}
Defensive patterns

Strategy: validation

Validate before calling

// Enforce: all attributes of a computed block are computed.
if block.Computed {
    for n, a := range block.Attributes {
        if a != nil && !a.Computed { return fmt.Errorf("%s must be computed under a Computed block", n) }
    }
}

Prevention

When it happens

Trigger: Marking a nested block Computed = true (typical for data-source/ephemeral/object attributes) but leaving one of its attributes as Optional-only or Required.

Common situations: Converting a config block to a computed output, framework migration where object attributes weren't all marked computed, partially-computed nested objects.

Related errors


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