hashicorp/terraform · error

%s%s: MinItems and MaxItems must match in NestingSingle mode

Error message

%s%s: MinItems and MaxItems must match in NestingSingle mode

What it means

In NestingSingle mode, MinItems and MaxItems must be equal (checked at lines 76-77): a single block is either present once or not, so there is no range. The validator first requires MinItems == MaxItems; only when they match does it then check they are 0 or 1 (rule 818).

Source

Thrown at internal/configs/configschema/internal_validate.go:77

		}
		if !blockS.Deprecated && blockS.DeprecationMessage != "" {
			multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: DeprecationMessage must not be set when Deprecated is false", prefix, name))
		}

		if blockS.MinItems < 0 || blockS.MaxItems < 0 {
			multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: MinItems and MaxItems must both be greater than zero", prefix, name))
		}

		// any nested blocks within a computed block must also be computed
		if b.Computed && !blockS.Computed {
			multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: all nested blocks within computed blocks must also be computed", prefix, name))
		}

		switch blockS.Nesting {
		case NestingSingle:
			switch {
			case blockS.MinItems != blockS.MaxItems:
				multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: MinItems and MaxItems must match in NestingSingle mode", prefix, name))
			case blockS.MinItems < 0 || blockS.MinItems > 1:
				multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: MinItems and MaxItems must be set to either 0 or 1 in NestingSingle mode", prefix, name))
			}
		case NestingGroup:
			if blockS.MinItems != 0 || blockS.MaxItems != 0 {
				multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: MinItems and MaxItems cannot be used in NestingGroup mode", prefix, name))
			}
			if blockS.Computed {
				multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: NestingGroup blocks cannot be computed", prefix, name))
			}
		case NestingList, NestingSet:
			if blockS.MinItems > blockS.MaxItems && blockS.MaxItems != 0 {
				multiErr = errors.Join(multiErr, fmt.Errorf("%s%s: MinItems must be less than or equal to MaxItems in %s mode", prefix, name, blockS.Nesting))
			}
			if blockS.Nesting == NestingSet {
				ety := blockS.Block.ImpliedType()
				if ety.HasDynamicTypes() {
					// This is not permitted because the HCL (cty) set implementation

View on GitHub (pinned to c9def3e214)

Solutions

  1. Set MinItems == MaxItems (both 0 for optional-single, or both 1 for required-single).
  2. If you need a 0..N range, use NestingList/NestingSet instead of NestingSingle.

Example fix

// before
"settings": {Nesting: configschema.NestingSingle, MinItems: 0, MaxItems: 1}

// after
"settings": {Nesting: configschema.NestingSingle, MinItems: 1, MaxItems: 1}  // required single
Defensive patterns

Strategy: validation

Validate before calling

if nb.Nesting == configschema.NestingSingle && nb.MinItems != nb.MaxItems {
    return fmt.Errorf("NestingSingle requires MinItems == MaxItems")
}

Prevention

When it happens

Trigger: Setting MinItems=0, MaxItems=1 (or any unequal pair) on a NestingSingle block.

Common situations: Confusing NestingSingle with NestingList semantics, generating schemas with a default MaxItems=0 paired with MinItems=1.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/bef7e587fe612b01. Report an issue: GitHub.