hashicorp/terraform · error

%s: Type and NestedType cannot both be set

Error message

%s: Type and NestedType cannot both be set

What it means

Raised when an Attribute has both a flat Type and a NestedType set. The two are mutually exclusive representations: Type describes a primitive/collection value, NestedType describes a structural object. Setting both is ambiguous. The validator at internal_validate.go:163-164 detects Type != NilType together with NestedType != nil. Note the message omits the prefix (a minor formatting quirk: errors.Join is called without the prior err and without the prefix variable).

Source

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

		err = errors.Join(err, fmt.Errorf("%s%s: must set Optional, Required or Computed", prefix, name))
	}
	if a.Optional && a.Required {
		err = errors.Join(err, fmt.Errorf("%s%s: cannot set both Optional and Required", prefix, name))
	}
	if a.Computed && a.Required {
		err = errors.Join(err, fmt.Errorf("%s%s: cannot set both Computed and Required", prefix, name))
	}
	if !a.Deprecated && a.DeprecationMessage != "" {
		err = errors.Join(err, fmt.Errorf("%s%s: DeprecationMessage must not be set when Deprecated is false", prefix, name))
	}

	if a.Type == cty.NilType && a.NestedType == nil {
		err = errors.Join(err, fmt.Errorf("%s%s: either Type or NestedType must be defined", prefix, name))
	}

	if a.Type != cty.NilType {
		if a.NestedType != nil {
			err = errors.Join(fmt.Errorf("%s: Type and NestedType cannot both be set", name))
		}
	}

	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

View on GitHub (pinned to c9def3e214)

Solutions

  1. If the attribute should be structural, remove the Type field and keep NestedType.
  2. If the attribute should be flat, remove the NestedType field and keep Type.
  3. Add a linter rule that rejects Attributes where both Type and NestedType are set.

Example fix

// before
"cfg": {Type: cty.String, NestedType: &Object{Nesting: NestingSingle, Attributes: ...}, Optional: true}

// after
"cfg": {NestedType: &Object{Nesting: NestingSingle, Attributes: ...}, Optional: true}
Defensive patterns

Strategy: validation

Validate before calling

func assertNotBothTypes(a *configschema.Attribute) error {
    if a.Type != cty.NilType && a.NestedType != nil {
        return fmt.Errorf("Type and NestedType cannot both be set")
    }
    return nil
}

Type guard

func hasSingleTypeRepresentation(a *configschema.Attribute) bool {
    return !(a.Type != cty.NilType && a.NestedType != nil)
}

Prevention

When it happens

Trigger: An Attribute struct literal with both Type: cty.String and NestedType: &Object{...}. internalValidate reaches line 163 (Type is non-nil) and line 164 (NestedType is non-nil) and emits the error.

Common situations: Converting a flat attribute to a nested object and forgetting to clear Type; merging two schema fragments where one set Type and the other NestedType; copy-paste during refactoring.

Related errors


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