{"record":{"id":"7b50525a93472006","repo":"googleapis/mcp-toolbox","slug":"failed-to-list-clusters-w-7b5052","errorCode":null,"errorMessage":"failed to list clusters: %w","messagePattern":"failed to list clusters: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/sources/dataproc/dataproc.go","lineNumber":179,"sourceCode":"\t}\n\tif pageToken != \"\" {\n\t\treq.PageToken = pageToken\n\t}\n\tif filter != \"\" {\n\t\treq.Filter = filter\n\t}\n\n\tit := client.ListClusters(ctx, req)\n\tps := 0\n\tif pageSize != nil {\n\t\tps = *pageSize\n\t}\n\tpager := iterator.NewPager(it, ps, req.PageToken)\n\n\tclusterPbs := []*dataprocpb.Cluster{}\n\tnextPageToken, err := pager.NextPage(&clusterPbs)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to list clusters: %w\", err)\n\t}\n\n\tclusters, err := ToClusters(clusterPbs, s.Region)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn ListClustersResponse{Clusters: clusters, NextPageToken: nextPageToken}, nil\n}\n\n// ToClusters converts a slice of protobuf Cluster messages to a slice of Cluster structs.\nfunc ToClusters(clusterPbs []*dataprocpb.Cluster, region string) ([]Cluster, error) {\n\tclusters := make([]Cluster, 0, len(clusterPbs))\n\tfor _, clusterPb := range clusterPbs {\n\t\tconsoleUrl := ClusterConsoleURLFromProto(clusterPb, region)\n\t\tlogsUrl := ClusterLogsURLFromProto(clusterPb, region)\n\n\t\tstate := \"STATE_UNSPECIFIED\"","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/sources/dataproc/dataproc.go#L161-L197","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Grant the caller IAM role roles/dataproc.viewer (or higher) on the project.","Verify the configured region matches where your clusters live.","Retry on transient failures (the pager error may include retryable gRPC statuses).","Inspect the wrapped (%w) error for the gRPC status code and retry the tool call."],"exampleFix":"// before\ngcloud projects add-iam-policy-binding PROJECT \\\n  --member=\"serviceAccount:sa@project.iam.gserviceaccount.com\" \\\n  --role=\"roles/dataproc.viewer\" // add if missing\n\n// after: role granted, list-clusters succeeds","handlingStrategy":"try-catch","validationCode":"// pre-check IAM via a lightweight call, e.g. testIamPermissions on the project\nok, err := resourcemanagerSvc.Projects.TestIamPermissions(project,\n    &cloudresourcemanager.TestIamPermissionsRequest{Permissions: []string{\"dataproc.clusters.list\"}}).Do()","typeGuard":"null","tryCatchPattern":"clusters, err := src.ListClusters(ctx, ...)\nif err != nil {\n    var apiErr *googleapi.Error\n    if errors.As(err, &apiErr) && apiErr.Code == 403 {\n        // grant roles/dataproc.viewer and retry\n    }\n    if isRetryable(err) {\n        // exponential backoff retry\n    }\n    return err\n}","preventionTips":["Grant the service account roles/dataproc.viewer before using the tool.","Pin the region config to where clusters actually run.","Handle page-token errors by restarting the listing from scratch."],"tags":["gcp","dataproc","pagination","iam"],"backgroundTag":"permission-denied","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}