{"record":{"id":"387cbfc572f2be6e","repo":"kubernetes/kops","slug":"error-fetching-cluster-v-w","errorCode":null,"errorMessage":"error fetching cluster %v: %w","messagePattern":"error fetching cluster (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/controllers/clusterapi/utils.go","lineNumber":80,"sourceCode":"\t}\n\n\tcapiClusterName := obj.GetLabels()[clusterv1.ClusterNameLabel]\n\tif capiClusterName == \"\" {\n\t\treturn nil, fmt.Errorf(\"label %q not set on %v\", clusterv1.ClusterNameLabel, id)\n\t}\n\n\tcapiCluster := &unstructured.Unstructured{}\n\tcapiCluster.SetGroupVersionKind(schema.GroupVersionKind{\n\t\tGroup:   \"cluster.x-k8s.io\",\n\t\tVersion: \"v1beta1\",\n\t\tKind:    \"Cluster\",\n\t})\n\tclusterKey := types.NamespacedName{\n\t\tNamespace: obj.GetNamespace(),\n\t\tName:      capiClusterName,\n\t}\n\tif err := kube.Get(ctx, clusterKey, capiCluster); err != nil {\n\t\treturn nil, fmt.Errorf(\"error fetching cluster %v: %w\", clusterKey, err)\n\t}\n\n\treturn capiCluster, nil\n}\n\nfunc getKopsClusterFromCAPICluster(ctx context.Context, kube client.Client, capiCluster *unstructured.Unstructured) (*kopsapi.Cluster, error) {\n\tvar clusterKey types.NamespacedName\n\n\tfor _, ownerRef := range capiCluster.GetOwnerReferences() {\n\t\tif ownerRef.Kind == \"Cluster\" && strings.HasPrefix(ownerRef.APIVersion, \"kops.k8s.io/\") {\n\t\t\tclusterKey = types.NamespacedName{\n\t\t\t\tNamespace: capiCluster.GetNamespace(),\n\t\t\t\tName:      ownerRef.Name,\n\t\t\t}\n\t\t}\n\t}\n\n\tif clusterKey.Name == \"\" {","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/controllers/clusterapi/utils.go#L62-L98","documentation":"After reading `cluster.x-k8s.io/cluster-name` from the object's labels, getCAPIClusterFromCAPIObject fetches the referenced cluster.x-k8s.io/v1beta1 Cluster (unstructured) from the same namespace. This error wraps any failure of that kube.Get — almost always a NotFound because the label points to a Cluster that does not exist (or was deleted), but it can also be an API/server error or RBAC denial.","triggerScenarios":"Reconcile -> getCAPIClusterFromCAPIObject where the object is labeled `cluster.x-k8s.io/cluster-name: X` but no Cluster named X exists in the object's namespace, the API server is unreachable, or the controller's ServiceAccount lacks get permission on cluster.x-k8s.io Clusters.","commonSituations":"Dangling label after the CAPI Cluster was deleted while dependent objects remain (finalizers, orphaned machines); typo in the label value or wrong namespace; CRD cluster.x-k8s.io Clusters not installed; RBAC not granted to the controller.","solutions":["Check the Cluster object exists: kubectl get cluster.x-k8s.io <name> -n <namespace>; recreate it if it was deleted","Clean up orphaned dependent objects (machines, control planes) whose owning Cluster is gone","Fix the `cluster.x-k8s.io/cluster-name` label value if it is misspelled or points to the wrong Cluster","Install the cluster.x-k8s.io/v1beta1 Cluster CRD if missing (clusterctl init / apply CAPI core components)","Verify RBAC allows the controller to get Clusters in the namespace"],"exampleFix":"# before: label references non-existent cluster\nmetadata:\n  labels:\n    cluster.x-k8s.io/cluster-name: deleted-cluster\n# after: point label at an existing Cluster (or recreate the Cluster)\nmetadata:\n  labels:\n    cluster.x-k8s.io/cluster-name: my-existing-cluster","handlingStrategy":"retry","validationCode":"// check the target Cluster exists before dependent operations\nkey := types.NamespacedName{Namespace: obj.GetNamespace(), Name: obj.GetLabels()[\"cluster.x-k8s.io/cluster-name\"]}\ncluster := &unstructured.Unstructured{}\ncluster.SetGroupVersionKind(schema.GroupVersionKind{Group: \"cluster.x-k8s.io\", Version: \"v1beta1\", Kind: \"Cluster\"})\nerr := kube.Get(ctx, key, cluster) // apierrors.IsNotFound(err) => stale label","typeGuard":"func clusterExists(ctx context.Context, kube client.Client, ns, name string) bool {\n\tc := &unstructured.Unstructured{}\n\tc.SetGroupVersionKind(schema.GroupVersionKind{Group: \"cluster.x-k8s.io\", Version: \"v1beta1\", Kind: \"Cluster\"})\n\treturn kube.Get(ctx, types.NamespacedName{Namespace: ns, Name: name}, c) == nil\n}","tryCatchPattern":"capiCluster, err := getCAPIClusterFromCAPIObject(ctx, kube, obj)\nif err != nil {\n\tif apierrors.IsNotFound(errors.Unwrap(err)) {\n\t\t// stale label or deleted cluster: drop orphaned object or requeue with backoff\n\t\treturn ctrl.Result{RequeueAfter: time.Minute}, nil\n\t}\n\treturn ctrl.Result{}, err // transient API error: rely on reconcile retry\n}","preventionTips":["Use ownerReferences/foreground deletion so dependents are cleaned up with their Cluster","Watch for Cluster deletion events and garbage-collect labeled dependents","Verify the cluster-name label value matches an actual Cluster name in the same namespace","Ensure the controller has RBAC get on cluster.x-k8s.io clusters"],"tags":["kubernetes","cluster-api","not-found","reconcile"],"backgroundTag":"resource-not-found","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}