kubernetes/kops · error

error building InstanceGroup from CAPI Machine: %w

Error message

error building InstanceGroup from CAPI Machine: %w

What it means

For CAPI-managed nodes with no direct InstanceGroup name, getNodeConfig synthesizes an InstanceGroup from the verified Cluster API Machine via s.buildInstanceGroupFromCAPI. If that synthesis fails (e.g. the Machine lacks required owner references, labels, or the kops cluster cannot be located from the Machine), the underlying error is wrapped with this message and the bootstrap request fails.

Source

Thrown at cmd/kops-controller/pkg/server/node_config.go:65

		}
		// CAPI path: the InstanceGroup is synthesized from the Machine and
		// the name never reaches the configBase path, so we don't validate it.
	} else if errs := kopsvalidation.ValidateInstanceGroupName(instanceGroupName, field.NewPath("instanceGroupName")); len(errs) > 0 {
		return nil, fmt.Errorf("invalid InstanceGroup name: %v", errs.ToAggregate())
	}

	var nodeConfig *nodeup.NodeConfig

	configBuilder := &commands.ConfigBuilder{
		Clientset:   s.clientset,
		ClusterName: s.opt.ClusterName,
	}

	if identity.CAPIMachine != nil && instanceGroupName == "" {
		// We have a CAPI Machine (but no instance group)
		instanceGroup, err := s.buildInstanceGroupFromCAPI(ctx, identity.CAPIMachine)
		if err != nil {
			return nil, fmt.Errorf("error building InstanceGroup from CAPI Machine: %w", err)
		}
		log.Info("built InstanceGroup from CAPI Machine", "instanceGroup", instanceGroup)
		configBuilder.InstanceGroup = instanceGroup
	} else if s.opt.Cloud == "metal" {
		configBuilder.InstanceGroupName = instanceGroupName
	} else {
		// Note: For now, we're assuming there is only a single cluster, and it is ours.
		// We therefore use the configured base path

		p := s.configBase.Join("igconfig", "node", instanceGroupName, "nodeupconfig.yaml")

		b, err := p.ReadFile(ctx)
		if err != nil {
			return nil, fmt.Errorf("error loading NodeupConfig %q: %v", p, err)
		}
		nodeConfig = &nodeup.NodeConfig{}
		nodeConfig.NodeupConfig = string(b)
	}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Read the wrapped inner error to see the concrete failure (missing label, not found, permissions) and fix that cause
  2. Ensure each CAPI Machine has the required cluster-name label and an ownerReference to the kops Cluster so buildInstanceGroupFromCAPI can resolve it
  3. Verify kops-controller can access the state store (configBase) and that the cluster spec is present
  4. Confirm the Machine belongs to the same cluster this kops-controller instance serves
Defensive patterns

Strategy: retry

Validate before calling

// pre-check the Machine carries the kops cluster-name label
if machine.Labels["kops.k8s.io/cluster"] == "" {
	return fmt.Errorf("machine %s lacks kops cluster label", machine.Name)
}

Try / catch

if strings.Contains(err.Error(), "error building InstanceGroup from CAPI Machine") {
	// inspect wrapped cause; requeue the bootstrap with backoff after fixing labels/state store access
}

Prevention

When it happens

Trigger: identity.CAPIMachine != nil and instanceGroupName == "", and buildInstanceGroupFromCAPI returns an error — commonly because the Machine's cluster-name label or ownerReference to the Cluster is missing/unresolvable, or the referenced kops Cluster/InstanceGroup data cannot be fetched from state store.

Common situations: Machine objects created by a CAPI provider without the kops-required labels/annotations; CAPI Machine belonging to a different cluster than the one kops-controller serves; state store permissions or connectivity problems when reading cluster config; mismatched kops/clusterapi controller versions.

Related errors


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