hashicorp/terraform · error

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

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` when the configured backend for the current working directory is not the HCP Terraform / TFE `cloud` backend, but the plan bookmark being shown is a remote cloud plan. The current backend type is asserted via `b.(*cloud.Cloud)`; on failure this error is produced. NOTE: there is a latent bug in the source — on the `!ok` branch `cl` is nil, so `cl.AppName()` will panic before this error is ever returned in builds without nil-guarding; treat any actual sighting as a potential panic.

Solutions

  1. Run `terraform show` in the directory whose backend is the same `cloud` block that produced the plan.
  2. Ensure `terraform init` has configured the cloud backend (the `cloud` block is present and logged in).
  3. If you only have the plan JSON, use `terraform show -json <file>` on the exported JSON instead of a cloud bookmark.
Defensive patterns

Strategy: validation

Validate before calling

// Validate the backend is cloud before attempting to read a cloud plan:
b, diags := c.backend(".", c.viewType)
if diags.HasErrors() { return nil, errUnusable(diags.Err(), "cloud plan") }
cl, ok := b.(*cloud.Cloud)
if !ok {
    name := "HCP Terraform"
    return nil, errUnusable(errors.New("current backend is not a cloud backend"), "cloud plan")
}

Type guard

// isCloudBackend narrows the backend to the cloud type without dereferencing nil.
func isCloudBackend(b backend.Backend) (*cloud.Cloud, bool) {
    cl, ok := b.(*cloud.Cloud)
    if !ok || cl == nil {
        return nil, false
    }
    return cl, true
}

Prevention

When it happens

Trigger: `terraform show <saved-plan>` is invoked with a `SavedPlanBookmark` produced by a cloud run, but the working directory's backend resolves to local, s3, remote, etc. — anything other than `*cloud.Cloud`.

Common situations: Checking out a saved cloud plan locally after switching the `backend`/`cloud` block to a local backend; running `terraform show` on a plan JSON copied from a cloud run in a directory that is not cloud-connected; CI that fetched a plan bookmark into a non-cloud workspace.

Related errors


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

Appendix: 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 d32a084675)