hashicorp/terraform · error

can't show a saved cloud plan unless the current root module

Error message

can't show a saved cloud plan unless the current root module is connected to %s

What it means

Returned by ShowCommand.getDataFromCloudPlan (show.go:307). A saved-plan bookmark references a cloud (HCP Terraform) run, but the active backend resolved by c.backend(".") is not *cloud.Cloud. Terraform asserts the backend must be the cloud backend to fetch the run's plan JSON; otherwise it returns this error (note: cl.AppName() is called on the failed type-assertion result, so the message embeds the cloud backend's app name).

Source

Thrown at internal/command/show.go:307

	} else if cp, ok := pf.Cloud(); ok {
		redacted := c.viewType != arguments.ViewJSON
		jsonPlan, err = c.getDataFromCloudPlan(cp, redacted)
	}

	return plan, jsonPlan, stateFile, config, err
}

func (c *ShowCommand) getDataFromCloudPlan(plan *cloudplan.SavedPlanBookmark, redacted bool) (*cloudplan.RemotePlanJSON, error) {
	// Set up the backend
	b, diags := c.backend(".", c.viewType)
	if diags.HasErrors() {
		return nil, errUnusable(diags.Err(), "cloud plan")
	}
	// Cloud plans only work if we're cloud.
	cl, ok := b.(*cloud.Cloud)
	if !ok {
		errMessage := fmt.Sprintf("can't show a saved cloud plan unless the current root module is connected to %s", cl.AppName())
		return nil, errUnusable(errors.New(errMessage), "cloud plan")
	}

	result, err := cl.ShowPlanForRun(context.Background(), plan.RunID, plan.Hostname, redacted)
	if err != nil {
		err = errUnusable(err, "cloud plan")
	}
	return result, err
}

// getDataFromPlanfileReader returns a plan, statefile, and config, extracted from a local plan file.
func getDataFromPlanfileReader(planReader *planfile.Reader, allowLanguageExperiments bool, variableValues map[string]arguments.UnparsedVariableValue) (*plans.Plan, *statefile.File, *configs.Config, error) {
	// Get plan
	plan, err := planReader.ReadPlan()
	if err != nil {
		return nil, nil, nil, err
	}

	// Get statefile

View on GitHub (pinned to c9def3e214)

Solutions

  1. Re-run from a directory whose backend block is `cloud {}` (same org/hostname) so getDataFromCloudPlan can call cl.ShowPlanForRun.
  2. If you only need the local plan, generate and show a local plan file (`terraform plan -out=tfplan` then `terraform show -json tfplan`) instead of a cloud run bookmark.
  3. Re-init so the backend matches the one that created the saved plan.

Example fix

# before: backend is local, plan is a cloud bookmark
 terraform show -json   # 'can't show a saved cloud plan...'
# after: use a cloud backend that matches the plan's run
 # edit backend block to cloud{} with correct org, then
 terraform init
 terraform show -json
Defensive patterns

Strategy: type-guard

Validate before calling

// Resolve the backend and check its type before calling getDataFromCloudPlan.
 b, _ := c.backend(".", viewType)
 if _, ok := b.(*cloud.Cloud); !ok {
     return errors.New("switch to a cloud backend to view this saved cloud plan")
 }

Type guard

func isCloudBackend(b backend.Backend) bool {
     _, ok := b.(*cloud.Cloud)
     return ok
 }

Prevention

When it happens

Trigger: Running `terraform show -json <plan>` (or show of a saved plan bookmark) when the working directory's backend is local/s3/etc., but the plan file/bookmark was produced by a cloud run; or the cloud backend block was removed/changed after the plan was saved.

Common situations: See trigger scenarios.

Related errors


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