{"record":{"id":"e4fc21db87d456f8","repo":"kubesphere/kubesphere","slug":"failed-to-fetch-cluster-s","errorCode":null,"errorMessage":"failed to fetch cluster: %s","messagePattern":"failed to fetch cluster: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/models/tenant/tenant.go","lineNumber":548,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to describe user: %s\", err)\n\t}\n\n\tgrantedClustersAnnotation := userDetail.Annotations[iamv1beta1.GrantedClustersAnnotation]\n\tvar grantedClusters sets.Set[string]\n\tif len(grantedClustersAnnotation) > 0 {\n\t\tgrantedClusters = sets.New(strings.Split(grantedClustersAnnotation, \",\")...)\n\t} else {\n\t\tgrantedClusters = sets.New[string]()\n\t}\n\tvar clusters []*clusterv1alpha1.Cluster\n\tfor _, grantedCluster := range grantedClusters.UnsortedList() {\n\t\tobj, err := t.resourceGetter.Get(clusterv1alpha1.ResourcesPluralCluster, \"\", grantedCluster)\n\t\tif err != nil {\n\t\t\tif errors.IsNotFound(err) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\treturn nil, fmt.Errorf(\"failed to fetch cluster: %s\", err)\n\t\t}\n\t\tcluster := obj.(*clusterv1alpha1.Cluster)\n\t\tclusters = append(clusters, cluster)\n\t}\n\n\titems := make([]runtime.Object, 0)\n\tfor _, cluster := range clusters {\n\t\titems = append(items, cluster)\n\t}\n\n\tclusterByRoleBinding := false\n\tif v, ok := queryParam.Filters[queryRoleBindingExists]; ok && v != \"\" {\n\t\tclusterByRoleBinding, err = strconv.ParseBool(string(v))\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t}\n","sourceCodeStart":530,"sourceCodeEnd":566,"githubUrl":"https://github.com/kubesphere/kubesphere/blob/04a29b5c601470fa6bc2f2e92358dcb802a0d414/pkg/models/tenant/tenant.go#L530-L566","documentation":"After resolving the user's granted clusters annotation, ListClusters fetches each granted cluster via resourceGetter. NotFound errors are skipped, but any other retrieval error is wrapped as 'failed to fetch cluster: %s'. This means a granted cluster reference could not be read for a non-not-found reason.","triggerScenarios":"Iterating granted cluster names from the user's GrantedClustersAnnotation when the cluster resource Get fails with an error other than NotFound — API server errors, permission failures at the resource layer, or informer cache errors.","commonSituations":"GrantedClustersAnnotation referencing clusters in a broken multi-cluster setup (host unable to reach agent clusters); cached informer out of sync after cluster deletion/recreation race; RBAC preventing the operator's own read of the cluster resource.","solutions":["Check the wrapped error to identify whether it's timeouts, RBAC, or cache issues","Clean up stale cluster names in the user's GrantedClustersAnnotation if clusters were deleted","Verify cluster CRs are healthy: `kubectl get cluster` and check agent connectivity for each cluster","Restart kubesphere-apiserver to refresh informer caches if reads fail transiently"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"var cl clusterv1alpha1.ClusterList\nif err := k8sClient.List(ctx, &cl); err != nil {\n    return fmt.Errorf(\"cluster resources unreadable: %w\", err)\n}","typeGuard":"func isFetchClusterFailure(err error) bool {\n    return err != nil && strings.HasPrefix(err.Error(), \"failed to fetch cluster: \")\n}","tryCatchPattern":"clusters, err := tenant.ListClusters(user, qp)\nif err != nil {\n    if isFetchClusterFailure(err) {\n        return degradedClusterList(qp) // serve partial data with a warning\n    }\n    return err\n}","preventionTips":["Keep GrantedClustersAnnotation consistent with actual cluster CRs","Prune stale granted cluster names when clusters are removed","Watch agent connectivity in multicluster setups","Retry transient Get failures with backoff"],"tags":["kubernetes","kubesphere","multicluster","resource-fetch"],"backgroundTag":null,"analyzedSha":"04a29b5c601470fa6bc2f2e92358dcb802a0d414","analyzedAt":"2026-09-03T18:33:15.017Z","contentChangedAt":"2026-09-03T18:33:15.017Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}