kubernetes/kops · error

providerID not set for node %q

Error message

providerID not set for node %q

What it means

IdentifyNode resolves a Kubernetes Node to its Azure identity. The first step reads node.Spec.ProviderID; if the field is empty the node has not yet been assigned a cloud provider identity, so the lookup cannot proceed and this error is thrown.

Source

Thrown at pkg/nodeidentity/azure/identify.go:74

// New creates and returns a a node identifier for Nodes running on Azure.
func New(cacheNodeidentityInfo bool) (nodeidentity.Identifier, error) {
	client, err := newClient()
	if err != nil {
		return nil, err
	}

	return &nodeIdentifier{
		azureClient:  client,
		cache:        expirationcache.NewTTLStore(stringKeyFunc, cacheTTL),
		cacheEnabled: cacheNodeidentityInfo,
	}, nil
}

// IdentifyNode queries Azure for the node identity information.
func (i *nodeIdentifier) IdentifyNode(ctx context.Context, node *corev1.Node) (*nodeidentity.Info, error) {
	providerID := node.Spec.ProviderID
	if providerID == "" {
		return nil, fmt.Errorf("providerID not set for node %q", node.Name)
	}
	if !strings.HasPrefix(providerID, "azure://") {
		return nil, fmt.Errorf("providerID %q not recognized for node %q", providerID, node.Name)
	}

	vmName, err := getVMNameFromProviderID(providerID)
	if err != nil {
		return nil, err
	}

	// If caching is enabled, try pulling nodeidentity.Info from the cache before doing an API call.
	if i.cacheEnabled {
		obj, exists, err := i.cache.GetByKey(vmName)
		if err != nil {
			klog.Warningf("Nodeidentity info cache lookup failure: %v", err)
		}
		if exists {
			return obj.(*nodeidentity.Info), nil

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Wait for the cloud-controller-manager to assign providerID, then retry: kubectl get node <name> -o jsonpath='{.spec.providerID}'
  2. Verify the Azure cloud controller manager is installed and running (kubelet with --cloud-provider=external, CCM pods healthy)
  3. If the node is permanent and CCM is healthy but providerID is still empty, check CCM logs for errors identifying the instance (IMDS/VMSS lookup failures)
  4. For transient races, add retry/backoff around IdentifyNode rather than treating the first failure as fatal

Example fix

// before (caller assumes providerID exists)
info, err := identifier.IdentifyNode(ctx, node)

// after (validate first)
if node.Spec.ProviderID == "" {
    return nil, fmt.Errorf("node %q has no providerID yet; waiting for cloud controller manager", node.Name)
}
info, err := identifier.IdentifyNode(ctx, node)
Defensive patterns

Strategy: validation

Validate before calling

if node.Spec.ProviderID == "" {
    return fmt.Errorf("node %q has no providerID yet", node.Name)
}

Type guard

func hasProviderID(node *corev1.Node) bool {
    return node != nil && node.Spec.ProviderID != ""
}

Try / catch

info, err := identifier.IdentifyNode(ctx, node)
if err != nil && strings.Contains(err.Error(), "providerID not set") {
    // node not yet registered with cloud; retry with backoff
}

Prevention

When it happens

Trigger: IdentifyNode is called for a Node whose spec.providerID is "" — typically a node registered before the cloud provider (cloud-controller-manager) assigned its providerID, or a node not managed by any cloud provider.

Common situations: Race at cluster bring-up: node joins before azure CCM sets providerID; CCM not installed/failing; nodes added manually via kubelet without --cloud-provider=external; node objects created by tooling that doesn't set providerID.

Related errors


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