kubernetes/kops · error
providerID was not set for node
Error message
providerID was not set for node %s
What it means
IdentifyNode resolves a Kubernetes Node to GCE instance identity info. It requires node.Spec.ProviderID to be set, because all subsequent lookups (project/zone/instance parsing and GCE API queries) derive from that string. If the providerID field is empty, there is nothing to identify the node with, so it fails fast.
Solutions
- Ensure the GCE cloud-controller-manager is running and has annotated/patched the Node (check that node.spec.providerID looks like gce://project/zone/instance-name).
- Wait for node initialization: newly joined nodes get their providerID set shortly after registration; re-run identification after reconciliation.
- If constructing the Node yourself (tests/tools), set Spec.ProviderID explicitly to "gce://<project>/<zone>/<instance>".
- Check kubelet flags: on GCE the kubelet/cloud provider must not run with --cloud-provider=none, which skips providerID assignment.
Example fix
// before
node := &corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: "gke-node-1"}}
info, err := identifier.IdentifyNode(ctx, node) // errors: providerID was not set
// after
node := &corev1.Node{ObjectMeta: metav1.ObjectMeta{Name: "gke-node-1"}, Spec: corev1.NodeSpec{ProviderID: "gce://my-project/us-central1-a/gke-node-1"}}
info, err := identifier.IdentifyNode(ctx, node) Defensive patterns
Strategy: validation
Validate before calling
if node.Spec.ProviderID == "" {
return fmt.Errorf("skip node %s: providerID not yet set", node.Name)
}
_ = identifier.IdentifyNode(ctx, node) 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 {
if strings.Contains(err.Error(), "providerID was not set") {
// requeue: providerID usually appears shortly after node registration
return requeueAfter(10 * time.Second)
}
return err
} Prevention
- Run the GCE cloud-controller-manager so providerID is always set on node registration.
- Before identifying, wait/poll until node.Spec.ProviderID is non-empty.
- Skip or requeue nodes lacking providerID instead of failing hard.
- In tests/fixtures, always populate Spec.ProviderID.
When it happens
Trigger: Calling IdentifyNode (directly or via the node-authorizer/identity controller) with a *corev1.Node whose Spec.ProviderID is "" — typically because the cloud-controller-manager or kubelet never populated it.
Common situations: Nodes registered by kubelet before the cloud provider integration set the provider ID; clusters where --cloud-provider=external is misconfigured so the GCE cloud controller never patches node.Spec.ProviderID; manually created Node objects in tests or fixtures; node objects restored from etcd backups missing spec updates.
Related errors
- providerID not recognized for node
- cannot find owner for instance
- error finding Machine with providerID
- found instance , but status is
- providerID did not match our project
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/c2b89cf8287187ef.
Report an issue: GitHub.
Appendix: source
Thrown at pkg/nodeidentity/gce/identify.go:99
}
klog.Infof("Found project=%q", project)
}
return &nodeIdentifier{
computeService: computeService,
project: project,
clusterName: clusterName,
capiManager: capiManager,
}, nil
}
// IdentifyNode queries GCE for the node identity information
func (i *nodeIdentifier) IdentifyNode(ctx context.Context, node *corev1.Node) (*nodeidentity.Info, error) {
// log := klog.FromContext(ctx)
providerID := node.Spec.ProviderID
if providerID == "" {
return nil, fmt.Errorf("providerID was not set for node %s", node.Name)
}
if !strings.HasPrefix(providerID, "gce://") {
return nil, fmt.Errorf("providerID %q not recognized for node %s", providerID, node.Name)
}
tokens := strings.Split(strings.TrimPrefix(providerID, "gce://"), "/")
if len(tokens) != 3 {
return nil, fmt.Errorf("providerID %q not recognized for node %s", providerID, node.Name)
}
project := tokens[0]
zone := tokens[1]
instanceName := tokens[2]
if project != i.project {
return nil, fmt.Errorf("providerID %q did not match our project %q", providerID, i.project)
}
View on GitHub (pinned to 4c8573c808)