hashicorp/terraform · error

couldn't read plan data for cloud run %s: %w

Error message

couldn't read plan data for cloud run %s: %w

What it means

Returned by ShowPlanForRun when fetching plan JSON (redacted or unredacted) fails with an error other than tfe.ErrResourceNotFound. The underlying cause is wrapped for diagnostics.

Source

Thrown at internal/cloud/backend_show.go:75

		// Bail, we can't use this.
		err = fmt.Errorf("can't display a cloud plan that is currently %s", r.Plan.Status)
		return nil, err
	}

	// Fetch the json plan!
	if redacted {
		jsonBytes, err = readRedactedPlan(ctx, b.client.BaseURL(), b.Token, r.Plan.ID)
	} else {
		jsonBytes, err = b.client.Plans.ReadJSONOutput(ctx, r.Plan.ID)
	}
	if err == tfe.ErrResourceNotFound {
		if redacted {
			return nil, fmt.Errorf("couldn't read plan data for cloud run %s; make sure you've run `terraform login` and that you have permission to view the run", runID)
		} else {
			return nil, fmt.Errorf("couldn't read unredacted JSON plan data for cloud run %s; make sure you've run `terraform login` and that you have admin permissions on the workspace", runID)
		}
	} else if err != nil {
		return nil, fmt.Errorf("couldn't read plan data for cloud run %s: %w", runID, err)
	}

	// Format a run header and footer
	header := strings.TrimSpace(fmt.Sprintf(runHeader, b.Hostname, b.Organization, r.Workspace.Name, r.ID))
	footer := strings.TrimSpace(statusFooter(r.Status, r.Actions.IsConfirmable, r.Workspace.Locked))

	out := &cloudplan.RemotePlanJSON{
		JSONBytes: jsonBytes,
		Redacted:  redacted,
		Mode:      mode,
		Qualities: opts,
		RunHeader: header,
		RunFooter: footer,
	}

	return out, nil
}

View on GitHub (pinned to c9def3e214)

Solutions

  1. Inspect the wrapped %w cause to classify (network vs auth vs server).
  2. Retry with backoff for transient (5xx, timeout) errors.
  3. Re-authenticate if the cause is an auth/permission error (401/403 surfaced as non-404).
  4. Check HCP/TFE status and plan-output endpoint health.

Example fix

// before
b, err := b.client.Plans.ReadJSONOutput(ctx, planID)
// after: classify and retry transient, surface persistent
if err != nil && !errors.Is(err, tfe.ErrResourceNotFound) {
    if isTransient(err) { return retry() }
    return fmt.Errorf("couldn't read plan data for cloud run %s: %w", runID, err)
}
Defensive patterns

Strategy: retry

Type guard

func isTransientPlanReadErr(err error) bool {
    var netErr net.Error
    if errors.As(err, &netErr) && netErr.Timeout() { return true }
    s := err.Error()
    return strings.Contains(s, "context deadline") || strings.Contains(s, "503") || strings.Contains(s, "502")
}

Try / catch

backoff := time.Second
for i := 0; i < 3; i++ {
    jsonBytes, err = read(b, ctx, r.Plan.ID)
    if err == nil { break }
    if errors.Is(err, tfe.ErrResourceNotFound) || !isTransientPlanReadErr(err) { break }
    time.Sleep(backoff); backoff *= 2
}

Prevention

When it happens

Trigger: readRedactedPlan or Plans.ReadJSONOutput returns a non-404 failure: 5xx, timeout, context cancellation, streaming/JSON decode error, auth token rejected mid-request.

Common situations: Transient API outage, network interruption during the streamed plan JSON read, expired token, or a malformed plan JSON object on the server.

Related errors


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