hashicorp/terraform · error

failed to retrieve project %s: %v

Error message

failed to retrieve project %s: %v

What it means

Returned in backend Workspaces() (workspace listing, e.g. terraform workspace list) at backend.go:663 when b.client.Projects.List returns an error that is NOT tfe.ErrResourceNotFound while resolving the configured project name. The %s is the project name and %v the raw TFE API error. ErrResourceNotFound is intentionally swallowed (project just filters to nothing).

Source

Thrown at internal/cloud/backend.go:663

		// The backend will end up applying both filters but that should always
		// be the same result set anyway.
		for _, tag := range options.TagBindings {
			if options.Tags != "" {
				options.Tags = options.Tags + ","
			}
			options.Tags = options.Tags + tag.Key
		}

	}
	log.Printf("[TRACE] cloud: Listing workspaces with tag bindings %q", b.WorkspaceMapping.DescribeTags())

	if b.WorkspaceMapping.Project != "" {
		listOpts := &tfe.ProjectListOptions{
			Name: b.WorkspaceMapping.Project,
		}
		projects, err := b.client.Projects.List(context.Background(), b.Organization, listOpts)
		if err != nil && err != tfe.ErrResourceNotFound {
			return nil, diags.Append(fmt.Errorf("failed to retrieve project %s: %v", listOpts.Name, err))
		}
		for _, p := range projects.Items {
			if p.Name == b.WorkspaceMapping.Project {
				options.ProjectID = p.ID
				break
			}
		}
	}

	for {
		wl, err := b.client.Workspaces.List(context.Background(), b.Organization, options)
		if err != nil {
			return nil, diags.Append(err)
		}

		for _, w := range wl.Items {
			names = append(names, w.Name)
		}

View on GitHub (pinned to c9def3e214)

Solutions

  1. Confirm the token's team has project-read permission in the organization.
  2. Retry on transient API errors or rate limits (the TFE client retries automatically; if still failing, back off).
  3. Verify TF_CLOUD_PROJECT / project name spelling and that the API host is healthy.

Example fix

// before: token cannot list projects
cloud { organization = "acme" workspaces { name = "dev" project = "platform" } }

// after: grant project read or remove project scoping
cloud { organization = "acme" workspaces { name = "dev" } }
Defensive patterns

Strategy: try-catch

Validate before calling

// Confirm project-read permission before listing workspaces.
if _, err := b.client.Projects.List(ctx, b.Organization, &tfe.ProjectListOptions{Name: project}); err != nil && !errors.Is(err, tfe.ErrResourceNotFound) {
    return fmt.Errorf("cannot read projects: %w; check token permissions", err)
}

Type guard

if errors.Is(err, tfe.ErrResourceNotFound) { /* tolerate */ } else { /* report */ }

Try / catch

// Distinguish tolerated 404 from real errors.
projects, err := b.client.Projects.List(ctx, org, opts)
if errors.Is(err, tfe.ErrResourceNotFound) {
    projects = nil // proceed with empty filter
} else if err != nil {
    return fmt.Errorf("failed to retrieve project %s: %v", project, err)
}

Prevention

When it happens

Trigger: A cloud backend with project = "X" (or TF_CLOUD_PROJECT=X); terraform workspace list triggers project lookup; the Projects.List API call fails with a non-404 error (401/403/500/rate-limit/network).

Common situations: Token lacks permission to read projects; TFE/HCP API outage or 5xx; rate limiting; transient network error hitting the API.

Related errors


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