googleapis/mcp-toolbox · error

failed to list clusters: %w

Error message

failed to list clusters: %w

What it means

Thrown by the Dataproc source's ListClusters when the pager's NextPage call fails while iterating ListClusters results from the ClusterController API. This surfaces GCP API errors (permission denied, region not found, quota, dead exeeded) during pagination.

Source

Thrown at internal/sources/dataproc/dataproc.go:179

	}
	if pageToken != "" {
		req.PageToken = pageToken
	}
	if filter != "" {
		req.Filter = filter
	}

	it := client.ListClusters(ctx, req)
	ps := 0
	if pageSize != nil {
		ps = *pageSize
	}
	pager := iterator.NewPager(it, ps, req.PageToken)

	clusterPbs := []*dataprocpb.Cluster{}
	nextPageToken, err := pager.NextPage(&clusterPbs)
	if err != nil {
		return nil, fmt.Errorf("failed to list clusters: %w", err)
	}

	clusters, err := ToClusters(clusterPbs, s.Region)
	if err != nil {
		return nil, err
	}

	return ListClustersResponse{Clusters: clusters, NextPageToken: nextPageToken}, nil
}

// ToClusters converts a slice of protobuf Cluster messages to a slice of Cluster structs.
func ToClusters(clusterPbs []*dataprocpb.Cluster, region string) ([]Cluster, error) {
	clusters := make([]Cluster, 0, len(clusterPbs))
	for _, clusterPb := range clusterPbs {
		consoleUrl := ClusterConsoleURLFromProto(clusterPb, region)
		logsUrl := ClusterLogsURLFromProto(clusterPb, region)

		state := "STATE_UNSPECIFIED"

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Grant the caller IAM role roles/dataproc.viewer (or higher) on the project.
  2. Verify the configured region matches where your clusters live.
  3. Retry on transient failures (the pager error may include retryable gRPC statuses).
  4. Inspect the wrapped (%w) error for the gRPC status code and retry the tool call.

Example fix

// before
gcloud projects add-iam-policy-binding PROJECT \
  --member="serviceAccount:sa@project.iam.gserviceaccount.com" \
  --role="roles/dataproc.viewer" // add if missing

// after: role granted, list-clusters succeeds
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check IAM via a lightweight call, e.g. testIamPermissions on the project
ok, err := resourcemanagerSvc.Projects.TestIamPermissions(project,
    &cloudresourcemanager.TestIamPermissionsRequest{Permissions: []string{"dataproc.clusters.list"}}).Do()

Type guard

null

Try / catch

clusters, err := src.ListClusters(ctx, ...)
if err != nil {
    var apiErr *googleapi.Error
    if errors.As(err, &apiErr) && apiErr.Code == 403 {
        // grant roles/dataproc.viewer and retry
    }
    if isRetryable(err) {
        // exponential backoff retry
    }
    return err
}

Prevention

When it happens

Trigger: Calling list-clusters where the API paged iteration fails: caller lacks dataproc.clusters.list permission, invalid region, project mismatch, or transient API error mid-page.

Common situations: Service account missing roles/dataproc.viewer; querying a region where Dataproc is not enabled; page token from a different session becoming invalid; hitting rate limits.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/7b50525a93472006. Report an issue: GitHub.