hashicorp/terraform · error

execution halted

Error message

execution halted

What it means

In NestingSingle mode MinItems must be 0 or 1 — at most one instance of the block is allowed. Values outside that range (e.g. 2, or negative) are invalid. This range check runs only when MinItems equals MaxItems (the prior check passed).

Solutions

  1. Set MinItems to 0 (optional) or 1 (required), keeping MaxItems equal.
  2. Use NestingList or NestingSet if the user must provide multiple instances.

Example fix

// before
"primary": { Nesting: configschema.NestingSingle, MinItems: 2, MaxItems: 2 },
// after
"primary": { Nesting: configschema.NestingSingle, MinItems: 1, MaxItems: 1 },
Defensive patterns

Strategy: validation

Validate before calling

// NestingSingle MinItems must be 0 or 1.
func validSingleRange(nb *configschema.NestedBlock) bool {
    return nb.Nesting != configschema.NestingSingle || (nb.MinItems >= 0 && nb.MinItems <= 1)
}

Type guard

func isZeroOrOne(n int) bool { return n == 0 || n == 1 }

Prevention

When it happens

Trigger: NestingSingle with MinItems set to 2 or more (or negative), with MaxItems equal. Guard at internal_validate.go:78 is `blockS.MinItems < 0 || blockS.MinItems > 1`.

Common situations: Believing NestingSingle can require multiple blocks; arithmetic that produces a value > 1 for the single-block count.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/66d35e1060483d55. Report an issue: GitHub.

Appendix: source

Thrown at internal/backend/local/backend_apply.go:136

			return
		}

		trivialPlan := !plan.Applyable
		hasUI := op.UIOut != nil && op.UIIn != nil
		mustConfirm := hasUI && !op.AutoApprove && !trivialPlan
		op.View.Plan(plan, schemas)

		if testHookStopPlanApply != nil {
			testHookStopPlanApply()
		}

		// Check if we've been stopped before going through confirmation, or
		// skipping confirmation in the case of -auto-approve.
		// This can currently happen if a single stop request was received
		// during the final batch of resource plan calls, so no operations were
		// forced to abort, and no errors were returned from Plan.
		if stopCtx.Err() != nil {
			diags = diags.Append(errors.New("execution halted"))
			runningOp.Result = backendrun.OperationFailure
			op.ReportResult(runningOp, diags)
			return
		}

		if mustConfirm {
			var desc, query string
			switch op.PlanMode {
			case plans.DestroyMode:
				if op.Workspace != "default" {
					query = "Do you really want to destroy all resources in workspace \"" + op.Workspace + "\"?"
				} else {
					query = "Do you really want to destroy all resources?"
				}
				desc = "Terraform will destroy all your managed infrastructure, as shown above.\n" +
					"There is no undo. Only 'yes' will be accepted to confirm."
			case plans.RefreshOnlyMode:
				if len(plan.ActionTargetAddrs) > 0 {

View on GitHub (pinned to d32a084675)