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 to

View on GitHub (pinned to 3561785c48)

Solutions

  1. Set a concrete flat type on the attribute: Type: cty.String (or cty.Number, cty.Bool, cty.List(cty.String), cty.Object({...}) as appropriate)
  2. 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
  3. 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

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


AI-assisted analysis of opentofu/opentofu@3561785c48 (2026-08-15). Data as JSON: /api/errors/bd02551abff1721e. Report an issue: GitHub.