hashicorp/terraform · error

remote backend doesn't support %s

Error message

remote backend doesn't support %s

What it means

Thrown by the remote (Terraform Cloud/Enterprise) backend when the plan operation carries a plans.PlanMode value that the backend's switch statement in backend_plan.go:302-317 does not recognize. Only NormalMode, RefreshOnlyMode, and DestroyMode are mapped to RunCreateOptions fields; any other mode reaches the default branch and is treated as a programming/contract defect (the code comment at line 310 explicitly says it should be updated for each new plan mode). It signals that a new plan mode was added to Terraform core without a corresponding case in this remote backend.

Source

Thrown at internal/backend/remote/backend_plan.go:315

		ConfigurationVersion: cv,
		Refresh:              tfe.Bool(op.PlanRefresh),
		Workspace:            w,
	}

	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, generalError(
			"Invalid plan mode",
			fmt.Errorf("remote backend doesn't support %s", 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.ForceReplace) != 0 {
		runOptions.ReplaceAddrs = make([]string, 0, len(op.ForceReplace))
		for _, addr := range op.ForceReplace {
			runOptions.ReplaceAddrs = append(runOptions.ReplaceAddrs, addr.String())
		}
	}

	r, err := b.client.Runs.Create(stopCtx, runOptions)

View on GitHub (pinned to c9def3e214)

Solutions

  1. Check the value of op.PlanMode at the call site and only forward NormalMode/RefreshOnlyMode/DestroyMode to the remote backend plan operation.
  2. Upgrade the remote backend package (this file) to the version that adds a switch case for the new plan mode, mapping it to the matching tfe.RunCreateOptions field.
  3. If you maintain a fork, add the missing case in backend_plan.go:302 and open/refresh upstream support for that plan mode.
  4. Downgrade the caller to a Terraform core version whose plan modes are all covered by the remote backend.

Example fix

// before
runOptions := buildRunOptions(op) // op.PlanMode == plans.SomeNewMode -> default branch errors

// after
switch op.PlanMode {
case plans.NormalMode:
case plans.RefreshOnlyMode:
    runOptions.RefreshOnly = tfe.Bool(true)
case plans.DestroyMode:
    runOptions.IsDestroy = tfe.Bool(true)
case plans.SomeNewMode:
    runOptions.SomeNewField = tfe.Bool(true) // add the case for the new mode
default:
    return nil, generalError("Invalid plan mode", fmt.Errorf("remote backend doesn't support %s", op.PlanMode))
}
Defensive patterns

Strategy: validation

Validate before calling

// Before invoking the remote backend plan operation, reject unsupported modes.
func supportedPlanMode(m plans.Mode) error {
    switch m {
    case plans.NormalMode, plans.RefreshOnlyMode, plans.DestroyMode:
        return nil
    }
    return fmt.Errorf("remote backend does not support plan mode %s; use a supported mode", m)
}

if err := supportedPlanMode(op.PlanMode); err != nil { return err }

Prevention

When it happens

Trigger: Calling the remote backend Operation with an op.PlanMode outside {plans.NormalMode, plans.RefreshOnlyMode, plans.DestroyMode}. Concretely this happens when Terraform core introduces a new plans.Mode constant and a CLI/wrapper passes it through to the remote backend's plan path before backend_plan.go is updated.

Common situations: A new Terraform release adds a plan mode (e.g. a future mode beyond refresh-only/destroy) but the user's remote backend code is from an older revision; or a custom fork/patch sets op.PlanMode to an experimental value. Mismatched Terraform CLI and backend library versions.

Related errors


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