hashicorp/terraform · error

failed to retrieve project

Error message

failed to retrieve project %s: %v

What it means

During the Workspaces() listing operation, when a project name is configured in the workspace mapping, the backend queries the TFE/HCP API for projects matching that name. If the Projects.List call fails with any error other than tfe.ErrResourceNotFound (which is silently tolerated), the error is wrapped and returned. This prevents listing workspaces scoped to a project that cannot be resolved.

Solutions

  1. Verify the project name is correct in your cloud workspaces block or TF_CLOUD_PROJECT env var.
  2. Ensure the API token has permissions to read projects in the organization.
  3. Retry the operation if the error is transient (rate limiting, server error).
  4. If the TFE instance does not support projects, remove the project attribute from the workspaces block.

Example fix

# before — project not supported or wrong name
cloud {
  workspaces {
    project = "nonexistent-or-unsupported"
  }
}

# after — remove project or use correct name
cloud {
  workspaces {
    name = "my-workspace"
  }
}
# Or with correct project:
cloud {
  workspaces {
    tags = ["env:prod"]
    project = "correct-project-name"
  }
}
Defensive patterns

Strategy: retry

Validate before calling

// Before listing workspaces, verify project is accessible
if b.WorkspaceMapping.Project != "" {
    _, err := b.client.Projects.List(ctx, b.Organization, &tfe.ProjectListOptions{
        Name: b.WorkspaceMapping.Project,
    })
    if err != nil && err != tfe.ErrResourceNotFound {
        return fmt.Errorf("cannot access projects API: %w", err)
    }
}

Try / catch

// Retry project listing on transient errors
for i := 0; i < 3; i++ {
    projects, err := b.client.Projects.List(ctx, b.Organization, listOpts)
    if err == nil || err == tfe.ErrResourceNotFound {
        break
    }
    if i == 2 {
        return nil, diags.Append(fmt.Errorf("failed to retrieve project %s: %v", listOpts.Name, err))
    }
    time.Sleep(time.Duration(1<<i) * time.Second)
}

Prevention

When it happens

Trigger: Calling b.client.Projects.List at backend.go:661 returns a non-nil, non-404 error. This happens when the API request itself fails: authentication errors, rate limiting, server errors, network issues, or the API version does not support the projects endpoint.

Common situations: The API token has insufficient permissions to list projects. The TFE instance version does not support the Projects API. Rate limiting or transient server errors during a workspace listing operation. Network connectivity issues between Terraform CLI and the TFE/HCP host.

Related errors


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

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