hashicorp/terraform · error
: Type and NestedType cannot both be set
Error message
%s: Type and NestedType cannot both be set
What it means
Thrown by Attribute.internalValidate when a provider/schema attribute defines both a Type (a primitive/collection cty type) and a NestedType (a block-style nested object). The schema model is mutually exclusive: an attribute is either a flat value of Type or a nested block described by NestedType, never both. Note this specific call uses errors.Join without the prior err accumulator, so on this branch earlier collected errors are dropped (likely a latent bug), but the trigger condition itself is genuine.
Solutions
- Inspect the offending attribute named in the error and pick one representation: keep Type for a scalar/list/map/set value OR keep NestedType for a nested block — not both.
- If you intended a nested block, set Attribute.Type = cty.NilType (leave it unset) and populate only Attribute.NestedType.
- If you intended a typed collection value (e.g. list of objects as a single value), drop NestedType and express the element shape inside Type, e.g. cty.List(cty.Object(...)).
- Add a unit test that calls schema.InternalValidate() / block.InternalValidate() right after construction so this fails at build time instead of runtime.
Example fix
// before
attr := &configschema.Attribute{
Type: cty.List(cty.String),
NestedType: &configschema.Object{
Nesting: configschema.NestingList,
Attributes: map[string]*configschema.Attribute{...},
},
Optional: true,
}
// after — choose nested block form
attr := &configschema.Attribute{
NestedType: &configschema.Object{
Nesting: configschema.NestingList,
Attributes: map[string]*configschema.Attribute{...},
},
Optional: true,
} Defensive patterns
Strategy: validation
Validate before calling
// Run before InternalValidate on any hand-built schema.
func assertTypeXORNestedType(a *configschema.Attribute) error {
if a.Type != cty.NilType && a.NestedType != nil {
return fmt.Errorf("attribute cannot set both Type and NestedType")
}
if a.Type == cty.NilType && a.NestedType == nil {
return fmt.Errorf("attribute must set either Type or NestedType")
}
return nil
} Type guard
func isBlockAttribute(a *configschema.Attribute) bool {
return a != nil && a.Type == cty.NilType && a.NestedType != nil
} Prevention
- Always construct Attributes through a small factory that takes either a Type or a *Object, never both.
- Call InternalValidate() in every provider unit test so mis-configured schemas fail at test time, not runtime.
- During SDK-to-framework migration, grep for 'Type:' alongside 'NestedType:' in the same literal to catch leftovers.
When it happens
Trigger: Building a *configschema.Attribute where both Attribute.Type is set (e.g. cty.String) and Attribute.NestedType is non-nil, then calling InternalValidate() on the containing Block/Object (which recurses into internalValidate). Typical in Terraform plugin SDK/terraform-plugin-framework schema conversion or hand-built schemas in tests.
Common situations: Migrating a provider schema between SDK v1 (Type) and terraform-plugin-framework (NestedType/Blocks) and forgetting to clear the old field; copy-pasting an attribute definition and adding a NestedType while leaving Type populated; converting a list-of-objects attribute represented as Type=cty.List(...) into a NestedType=NestingList block without removing Type.
Related errors
- object schema nesting mode is invalid
- : attribute schema is nil
- : NestingSet attributes may not contain attributes of…
- : NestingSet attributes may not contain WriteOnly attributes
- Apply discarded.
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/e2b10d09a3593ff5.
Report an issue: GitHub.
Appendix: 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 willView on GitHub (pinned to d32a084675)