hashicorp/terraform · error
%s%s: either Type or NestedType must be defined
Error message
%s%s: either Type or NestedType must be defined
What it means
Raised when an Attribute has neither Type nor NestedType set. Every attribute must carry a type — either a flat cty.Type or a structural *Object via NestedType; an attribute with neither has no representable value. The check at internal_validate.go:159 tests for Type==cty.NilType && NestedType==nil.
Source
Thrown at internal/configs/configschema/internal_validate.go:160
if !validName.MatchString(name) {
err = errors.Join(err, fmt.Errorf("%s%s: name may contain only lowercase letters, digits and underscores", prefix, name))
}
*/
if !a.Optional && !a.Required && !a.Computed {
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 toView on GitHub (pinned to c9def3e214)
Solutions
- Set Type to a concrete cty type (e.g. cty.String, cty.List(cty.Number)).
- If the attribute is a structural object, set NestedType to a populated *Object with a NestingMode.
- Validate schemas in unit tests so untyped attributes fail immediately.
Example fix
// before
"name": {Optional: true},
// after
"name": {Type: cty.String, Optional: true} Defensive patterns
Strategy: validation
Validate before calling
func assertHasType(a *configschema.Attribute) error {
if a.Type == cty.NilType && a.NestedType == nil {
return fmt.Errorf("attribute must define Type or NestedType")
}
return nil
} Type guard
func hasTypeOrNestedType(a *configschema.Attribute) bool {
return a.Type != cty.NilType || a.NestedType != nil
} Prevention
- Every attribute needs exactly one type representation: flat Type or structural NestedType.
- Define attributes via helpers that require a type parameter, so untyped literals cannot be expressed.
- Run InternalValidate in tests to catch missing types early.
When it happens
Trigger: An Attribute struct literal with Optional: true but no Type or NestedType field. internalValidate reaches line 159 and the conjunction is true.
Common situations: Adding an attribute and forgetting its type; refactoring that moved the type into a helper returning the zero Type; copy-pasting a placeholder attribute that was never filled in.
Related errors
- %s: Type and NestedType cannot both be set
- %s%s: NestingSet attributes may not contain attributes of ct
- %s%s: NestingSet attributes may not contain WriteOnly attrib
- attribute schema is nil
- %s%s: must set Optional, Required or Computed
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/4c0a607db66f107f.
Report an issue: GitHub.