hashicorp/terraform · error

doesn't support

Error message

%s doesn't support %s

What it means

Thrown in the default branch of the switch over op.PlanMode in the cloud plan-creation path. The switch handles NormalMode, RefreshOnlyMode, and DestroyMode explicitly; any other value is rejected because there is no mapping to a tfe.RunCreateOptions field. The comment explicitly states this is a developer guard: it should be updated whenever a new plan mode is added.

Solutions

  1. This is almost always an internal Terraform defect — report it to the Terraform team with the op.PlanMode value from the message.
  2. If running a fork, add a case for the new plan mode mapping it to the correct RunCreateOptions field.
  3. Downgrade to a stable Terraform release where the cloud backend and core plan modes are in sync.
  4. Avoid the unsupported flag combination that surfaces the new mode until the backend is updated.

Example fix

// before
case plans.DestroyMode:
    runOptions.IsDestroy = tfe.Bool(true)
default:
    return nil, b.generalError("Invalid plan mode", ...)
// after - add the missing mode mapping
case plans.DestroyMode:
    runOptions.IsDestroy = tfe.Bool(true)
case plans.NewMode:
    runOptions.NewField = tfe.Bool(true)
default:
    return nil, b.generalError("Invalid plan mode", ...)
Defensive patterns

Strategy: validation

Validate before calling

// Guard at the boundary before constructing the operation.
switch op.PlanMode {
case plans.NormalMode, plans.RefreshOnlyMode, plans.DestroyMode:
default:
    return fmt.Errorf("unsupported plan mode: %v", op.PlanMode)
}

Type guard

// Narrow plan mode to supported values.
func isSupportedPlanMode(m plans.Mode) bool {
    switch m {
    case plans.NormalMode, plans.RefreshOnlyMode, plans.DestroyMode:
        return true
    }
    return false
}

Prevention

When it happens

Trigger: A new plans.Mode constant was added to Terraform core without a corresponding case in this switch. This is an internal Terraform bug, not a user config error — op.PlanMode is set by the CLI flags (-destroy, -refresh-only), which cannot produce an unmapped value through normal use.

Common situations: Running a custom/development Terraform build that added a plan mode without updating the cloud backend; a plugin or fork that injects an unexpected PlanMode value; version skew between terraform-core and the cloud backend package.

Related errors


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

Appendix: source

Thrown at internal/cloud/backend_plan.go:164

		Workspace:            w,
		AutoApply:            tfe.Bool(op.AutoApprove),
		SavePlan:             tfe.Bool(op.PlanOutPath != ""),
	}

	switch op.PlanMode {
	case plans.NormalMode:
		// okay, but we don't need to do anything special for this
	case plans.RefreshOnlyMode:
		runOptions.RefreshOnly = tfe.Bool(true)
	case plans.DestroyMode:
		runOptions.IsDestroy = tfe.Bool(true)
	default:
		// Shouldn't get here because we should update this for each new
		// plan mode we add, mapping it to the corresponding RunCreateOptions
		// field.
		return nil, b.generalError(
			"Invalid plan mode",
			fmt.Errorf("%s doesn't support %s", b.appName, op.PlanMode),
		)
	}

	if len(op.Targets) != 0 {
		runOptions.TargetAddrs = make([]string, 0, len(op.Targets))
		for _, addr := range op.Targets {
			runOptions.TargetAddrs = append(runOptions.TargetAddrs, addr.String())
		}
	}

	if len(op.ActionTargets) != 0 {
		if len(op.ActionTargets) > 1 {
			// For now, we only support a single action from the command line.
			// We've future proofed the API and inputs so we can send multiple
			// but versions of Terraform will enforce this both here, and
			// on the other side.
			//
			// It shouldn't actually be possible to reach here anyway - we're

View on GitHub (pinned to d32a084675)