{"record":{"id":"bd02551abff1721e","repo":"opentofu/opentofu","slug":"s-s-either-type-or-nestedtype-must-be-defined","errorCode":null,"errorMessage":"%s%s: either Type or NestedType must be defined","messagePattern":"(.+?)(.+?): either Type or NestedType must be defined","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/configs/configschema/internal_validate.go","lineNumber":128,"sourceCode":"\tvar err *multierror.Error\n\n\t/* FIXME: this validation breaks certain existing providers and cannot be enforced without coordination.\n\tif !validName.MatchString(name) {\n\t\terr = multierror.Append(err, fmt.Errorf(\"%s%s: name may contain only lowercase letters, digits and underscores\", prefix, name))\n\t}\n\t*/\n\tif !a.Optional && !a.Required && !a.Computed {\n\t\terr = multierror.Append(err, fmt.Errorf(\"%s%s: must set Optional, Required or Computed\", prefix, name))\n\t}\n\tif a.Optional && a.Required {\n\t\terr = multierror.Append(err, fmt.Errorf(\"%s%s: cannot set both Optional and Required\", prefix, name))\n\t}\n\tif a.Computed && a.Required {\n\t\terr = multierror.Append(err, fmt.Errorf(\"%s%s: cannot set both Computed and Required\", prefix, name))\n\t}\n\n\tif a.Type == cty.NilType && a.NestedType == nil {\n\t\terr = multierror.Append(err, fmt.Errorf(\"%s%s: either Type or NestedType must be defined\", prefix, name))\n\t}\n\n\tif a.Type != cty.NilType {\n\t\tif a.NestedType != nil {\n\t\t\terr = multierror.Append(err, fmt.Errorf(\"%s: Type and NestedType cannot both be set\", name))\n\t\t}\n\t}\n\n\tif a.NestedType != nil {\n\t\tswitch a.NestedType.Nesting {\n\t\tcase NestingSingle, NestingMap:\n\t\t\t// no validations to perform\n\t\tcase NestingList, NestingSet:\n\t\t\tif a.NestedType.Nesting == NestingSet {\n\t\t\t\tety := a.ImpliedType()\n\t\t\t\tif ety.HasDynamicTypes() {\n\t\t\t\t\t// This is not permitted because the HCL (cty) set implementation\n\t\t\t\t\t// needs to know the exact type of set elements in order to","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/opentofu/opentofu/blob/3561785c48c1ce615e7c50261bd351f26053efa2/internal/configs/configschema/internal_validate.go#L110-L146","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\n\"size\": { Optional: true, Computed: true },\n\n// after\n\"size\": { Type: cty.Number, Optional: true, Computed: true },","handlingStrategy":"validation","validationCode":"func validateAttrShapes(b *configschema.Block) error {\n\tvar errs []error\n\tfor name, attr := range b.Attributes {\n\t\tif attr.Type == cty.NilType && attr.NestedType == nil {\n\t\t\terrs = append(errs, fmt.Errorf(\"attribute %q has neither Type nor NestedType\", name))\n\t\t}\n\t}\n\treturn errors.Join(errs...)\n}\n// run before Block.InternalValidate / shipping the schema","typeGuard":"func hasValueShape(a *configschema.Attribute) bool {\n\treturn a.Type != cty.NilType || a.NestedType != nil\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["schema","provider","validation","configschema","protocol6"],"backgroundTag":null,"analyzedSha":"3561785c48c1ce615e7c50261bd351f26053efa2","analyzedAt":"2026-08-15T23:27:16.226Z","schemaVersion":2},"datasetVersion":"2026-08-16T03:17:38.424Z"}