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), nilView on GitHub (pinned to 4c8573c808)
Solutions
- Wait for the cloud-controller-manager to assign providerID, then retry: kubectl get node <name> -o jsonpath='{.spec.providerID}'
- Verify the Azure cloud controller manager is installed and running (kubelet with --cloud-provider=external, CCM pods healthy)
- 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)
- 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
- Run the Azure cloud controller manager so providerIDs get set on registration
- Retry with backoff during node bring-up instead of failing immediately
- Ensure kubelet runs with --cloud-provider=external
- Alert on nodes that stay without providerID beyond a grace period
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
- unknown providerID : %s
- node not set
- unexpected subnet type: for InstanceGroup %q; type was %s
- malformed format of image urn: %s
- empty subscription ID
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/cda87a07097ff826.
Report an issue: GitHub.