opentofu/opentofu · error
%s%s: either Type or NestedType must be defined
Error message
%s%s: either Type or NestedType must be defined
What it means
Part of configschema's internal schema validation, which OpenTofu core runs on every provider schema it receives (internal/providers/schemas.go calls Block.InternalValidate for provider/resource/data-source schemas; the legacy helper/schema shim also self-validates). Every attribute must declare exactly one value shape: a flat cty type in Type, or a nested object in NestedType. This error fires when Attribute.internalValidate sees Type == cty.NilType and NestedType == nil, meaning the attribute describes no value type at all.
Source
Thrown at internal/configs/configschema/internal_validate.go:128
var err *multierror.Error
/* FIXME: this validation breaks certain existing providers and cannot be enforced without coordination.
if !validName.MatchString(name) {
err = multierror.Append(err, fmt.Errorf("%s%s: name may contain only lowercase letters, digits and underscores", prefix, name))
}
*/
if !a.Optional && !a.Required && !a.Computed {
err = multierror.Append(err, fmt.Errorf("%s%s: must set Optional, Required or Computed", prefix, name))
}
if a.Optional && a.Required {
err = multierror.Append(err, fmt.Errorf("%s%s: cannot set both Optional and Required", prefix, name))
}
if a.Computed && a.Required {
err = multierror.Append(err, fmt.Errorf("%s%s: cannot set both Computed and Required", prefix, name))
}
if a.Type == cty.NilType && a.NestedType == nil {
err = multierror.Append(err, fmt.Errorf("%s%s: either Type or NestedType must be defined", prefix, name))
}
if a.Type != cty.NilType {
if a.NestedType != nil {
err = multierror.Append(err, fmt.Errorf("%s: Type and NestedType cannot both be set", name))
}
}
if a.NestedType != nil {
switch a.NestedType.Nesting {
case NestingSingle, NestingMap:
// 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 3561785c48)
Solutions
- Set a concrete flat type on the attribute: Type: cty.String (or cty.Number, cty.Bool, cty.List(cty.String), cty.Object({...}) as appropriate)
- If the attribute is a structured object needing per-attribute Optional/Required/Computed metadata, set NestedType: &configschema.Object{Nesting: configschema.NestingSingle, Attributes: ...} and leave Type unset
- Re-run InternalValidate and fix any sibling errors returned in the same multierror (701-704 family) before retrying the tofu command
Example fix
// before
"size": { Optional: true, Computed: true },
// after
"size": { Type: cty.Number, Optional: true, Computed: true }, Defensive patterns
Strategy: validation
Validate before calling
func validateAttrShapes(b *configschema.Block) error {
var errs []error
for name, attr := range b.Attributes {
if attr.Type == cty.NilType && attr.NestedType == nil {
errs = append(errs, fmt.Errorf("attribute %q has neither Type nor NestedType", name))
}
}
return errors.Join(errs...)
}
// run before Block.InternalValidate / shipping the schema Type guard
func hasValueShape(a *configschema.Attribute) bool {
return a.Type != cty.NilType || a.NestedType != nil
} Prevention
- Call Block.InternalValidate() in provider unit tests and CI so typeless attributes fail the build, not the CLI
- Construct attributes via helpers that take a cty.Type argument, making a typeless attribute hard to express
- When decoding schema JSON, reject attributes missing a type field instead of accepting a zero value
When it happens
Trigger: A provider, mock-provider, or test schema containing an attribute literal with neither Type nor NestedType, e.g. &configschema.Attribute{Optional: true}. It surfaces when core validates the schema during provider schema fetch (tofu init/validate/plan) or when helper/schema Provider.InternalValidate runs in provider tests.
Common situations: Writing mock provider schemas for tofu test blocks or acceptance tests; migrating between SDKv2 and protocol 6 (NestedType only exists in protocol 6); hand-rolled configschema construction in codegen or tests where the Type field was simply forgotten.
Related errors
- %s: Type and NestedType cannot both be set
- missing provider schema
- Invalid attribute schema: NestedType and Type cannot both be
- Unknown validation type: %#v
- missing provider schema
AI-assisted analysis of opentofu/opentofu@3561785c48 (2026-08-15).
Data as JSON: /api/errors/bd02551abff1721e.
Report an issue: GitHub.