kubernetes/kops · error

error fetching cluster %v: %w

Error message

error fetching cluster %v: %w

What it means

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.

Source

Thrown at pkg/controllers/clusterapi/utils.go:80

	}

	capiClusterName := obj.GetLabels()[clusterv1.ClusterNameLabel]
	if capiClusterName == "" {
		return nil, fmt.Errorf("label %q not set on %v", clusterv1.ClusterNameLabel, id)
	}

	capiCluster := &unstructured.Unstructured{}
	capiCluster.SetGroupVersionKind(schema.GroupVersionKind{
		Group:   "cluster.x-k8s.io",
		Version: "v1beta1",
		Kind:    "Cluster",
	})
	clusterKey := types.NamespacedName{
		Namespace: obj.GetNamespace(),
		Name:      capiClusterName,
	}
	if err := kube.Get(ctx, clusterKey, capiCluster); err != nil {
		return nil, fmt.Errorf("error fetching cluster %v: %w", clusterKey, err)
	}

	return capiCluster, nil
}

func getKopsClusterFromCAPICluster(ctx context.Context, kube client.Client, capiCluster *unstructured.Unstructured) (*kopsapi.Cluster, error) {
	var clusterKey types.NamespacedName

	for _, ownerRef := range capiCluster.GetOwnerReferences() {
		if ownerRef.Kind == "Cluster" && strings.HasPrefix(ownerRef.APIVersion, "kops.k8s.io/") {
			clusterKey = types.NamespacedName{
				Namespace: capiCluster.GetNamespace(),
				Name:      ownerRef.Name,
			}
		}
	}

	if clusterKey.Name == "" {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check the Cluster object exists: kubectl get cluster.x-k8s.io <name> -n <namespace>; recreate it if it was deleted
  2. Clean up orphaned dependent objects (machines, control planes) whose owning Cluster is gone
  3. Fix the `cluster.x-k8s.io/cluster-name` label value if it is misspelled or points to the wrong Cluster
  4. Install the cluster.x-k8s.io/v1beta1 Cluster CRD if missing (clusterctl init / apply CAPI core components)
  5. Verify RBAC allows the controller to get Clusters in the namespace

Example fix

# before: label references non-existent cluster
metadata:
  labels:
    cluster.x-k8s.io/cluster-name: deleted-cluster
# after: point label at an existing Cluster (or recreate the Cluster)
metadata:
  labels:
    cluster.x-k8s.io/cluster-name: my-existing-cluster
Defensive patterns

Strategy: retry

Validate before calling

// check the target Cluster exists before dependent operations
key := types.NamespacedName{Namespace: obj.GetNamespace(), Name: obj.GetLabels()["cluster.x-k8s.io/cluster-name"]}
cluster := &unstructured.Unstructured{}
cluster.SetGroupVersionKind(schema.GroupVersionKind{Group: "cluster.x-k8s.io", Version: "v1beta1", Kind: "Cluster"})
err := kube.Get(ctx, key, cluster) // apierrors.IsNotFound(err) => stale label

Type guard

func clusterExists(ctx context.Context, kube client.Client, ns, name string) bool {
	c := &unstructured.Unstructured{}
	c.SetGroupVersionKind(schema.GroupVersionKind{Group: "cluster.x-k8s.io", Version: "v1beta1", Kind: "Cluster"})
	return kube.Get(ctx, types.NamespacedName{Namespace: ns, Name: name}, c) == nil
}

Try / catch

capiCluster, err := getCAPIClusterFromCAPIObject(ctx, kube, obj)
if err != nil {
	if apierrors.IsNotFound(errors.Unwrap(err)) {
		// stale label or deleted cluster: drop orphaned object or requeue with backoff
		return ctrl.Result{RequeueAfter: time.Minute}, nil
	}
	return ctrl.Result{}, err // transient API error: rely on reconcile retry
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/387cbfc572f2be6e. Report an issue: GitHub.