kubernetes/kops · error

cluster ownerRef not set on CAPI cluster %v/%v

Error message

cluster ownerRef not set on CAPI cluster %v/%v

What it means

getKopsClusterFromCAPICluster finds the kops Cluster that owns a CAPI Cluster by scanning capiCluster's ownerReferences for one with Kind "Cluster" and APIVersion prefixed "kops.k8s.io/". This error is thrown when no such owner reference exists, meaning the CAPI Cluster is not linked to any kops.k8s.io Cluster and the kops Cluster name cannot be derived.

Source

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

	}

	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 == "" {
		return nil, fmt.Errorf("cluster ownerRef not set on CAPI cluster %v/%v", capiCluster.GetNamespace(), capiCluster.GetName())
	}

	cluster := &kopsapi.Cluster{}
	if err := kube.Get(ctx, clusterKey, cluster); err != nil {
		return nil, fmt.Errorf("error fetching cluster %v: %w", clusterKey, err)
	}

	return cluster, nil
}

func getKopsControlPlaneFromCAPICluster(ctx context.Context, kube client.Client, capiCluster *unstructured.Unstructured) (*v1beta1.KopsControlPlane, error) {
	capiClusterKey := types.NamespacedName{
		Namespace: capiCluster.GetNamespace(),
		Name:      capiCluster.GetName(),
	}
	name, _, _ := unstructured.NestedString(capiCluster.Object, "spec", "controlPlaneRef", "name")
	if name == "" {
		return nil, fmt.Errorf("controlPlaneRef.name not set for %v", capiClusterKey)

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Ensure the CAPI Cluster is created by the kops CAPI machinery so it sets the kops.k8s.io Cluster ownerRef; delete and recreate through the normal flow
  2. Manually add the correct ownerReference (apiVersion: kops.k8s.io/v1alpha2, kind: Cluster, name: <kops-cluster>) to the CAPI Cluster
  3. Verify the kops Cluster exists in the same namespace and its name matches the ownerRef
  4. Check for API version changes across kops upgrades that break the strings.HasPrefix(ownerRef.APIVersion, "kops.k8s.io/") match

Example fix

# before: CAPI Cluster without kops ownerRef
metadata:
  name: my-capi-cluster
  ownerReferences: []
# after
metadata:
  name: my-capi-cluster
  ownerReferences:
  - apiVersion: kops.k8s.io/v1alpha2
    kind: Cluster
    name: my-kops-cluster
    uid: <uid>
    controller: true
Defensive patterns

Strategy: validation

Validate before calling

func hasKopsOwnerRef(capiCluster *unstructured.Unstructured) bool {
	for _, ref := range capiCluster.GetOwnerReferences() {
		if ref.Kind == "Cluster" && strings.HasPrefix(ref.APIVersion, "kops.k8s.io/") {
			return ref.Name != ""
		}
	}
	return false
}
// skip reconciliation until hasKopsOwnerRef(capiCluster) is true

Type guard

func kopsOwnerClusterKey(capiCluster *unstructured.Unstructured) (types.NamespacedName, bool) {
	for _, ref := range capiCluster.GetOwnerReferences() {
		if ref.Kind == "Cluster" && strings.HasPrefix(ref.APIVersion, "kops.k8s.io/") && ref.Name != "" {
			return types.NamespacedName{Namespace: capiCluster.GetNamespace(), Name: ref.Name}, true
		}
	}
	return types.NamespacedName{}, false
}

Prevention

When it happens

Trigger: Reconcile -> getKopsClusterFromCAPICluster where the CAPI Cluster object has an empty ownerReferences list, or owner references exist but none matches Kind=Cluster with APIVersion kops.k8s.io/* (e.g. owner is another kind, or a different API group).

Common situations: CAPI Cluster created manually instead of by the kops control-plane controller that normally sets the kops ownerRef; ownerRef stripped by copy/edit of the manifest; wrong owner kind or API version (e.g. kops.k8s.io vs another group) after a version migration.

Related errors


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