kubernetes/kops · warning

found instance %q, but status is %q

Error message

found instance %q, but status is %q

What it means

After fetching the instance from the GCE API, IdentifyNode only proceeds if the instance status is "RUNNING". Instances in PROVISIONING, STAGING, TERMINATED, or STOPPED states cannot be reliably identified (labels/metadata may be incomplete or the node is going away), so the identification is aborted with this message.

Source

Thrown at pkg/nodeidentity/gce/identify.go:125

		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)
	}

	instance, err := i.getInstance(zone, instanceName)
	if err != nil {
		return nil, err
	}

	instanceStatus := instance.Status
	if instanceStatus != "RUNNING" {
		return nil, fmt.Errorf("found instance %q, but status is %q", instanceName, instanceStatus)
	}

	capgRole := instance.Labels[LabelKeyCAPIRoleName]

	var capiMachine *clusterapi.Machine

	if i.capiManager != nil && capgRole != "" {
		providerID := "gce://" + project + "/" + zone + "/" + instanceName

		m, err := i.capiManager.FindMachineByProviderID(ctx, providerID)
		if err != nil {
			return nil, fmt.Errorf("error finding Machine with providerID %q: %w", providerID, err)
		}
		capiMachine = m
	}

	var igName string
	if capiMachine == nil {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Re-run identification once the instance is RUNNING (TRANSIENT — wait/retry, e.g. with backoff).
  2. If the instance is TERMINATED and the node should be gone, delete the stale Node object instead of identifying it.
  3. For preemptible/spot instances, expect frequent restarts and handle this error by requeueing.
  4. Check GCE console / `gcloud compute instances describe <name> --zone <zone> --format='value(status)'` to see actual state and why.

Example fix

// before
info, err := id.IdentifyNode(ctx, node) // instance still PROVISIONING
// after
err := wait.PollImmediate(5*time.Second, 2*time.Minute, func() (bool, error) {
    _, err := id.IdentifyNode(ctx, node)
    return err == nil, nil // retry until instance is RUNNING
})
Defensive patterns

Strategy: retry

Validate before calling

status, err := computeSvc.Instances.Get(project, zone, instanceName).Do()
if err == nil && status.Status != "RUNNING" {
    return fmt.Errorf("instance %s not ready (status %s); retry later", instanceName, status.Status)
}

Type guard

func isRunning(inst *compute.Instance) bool {
    return inst != nil && inst.Status == "RUNNING"
}

Try / catch

info, err := identifier.IdentifyNode(ctx, node)
if err != nil && strings.Contains(err.Error(), "but status is") {
    // transient: instance starting/stopping; requeue with backoff
    return requeueAfter(30 * time.Second)
}

Prevention

When it happens

Trigger: Calling IdentifyNode for a node whose GCE instance exists but whose Status field returned by compute.Instances.Get is anything other than "RUNNING" — e.g. the instance is being deleted, stopped, or just starting.

Common situations: Node deleted concurrently with identification (autoscaler scale-down); instance stopped manually or preempted; a Node object lingering in the k8s API after its VM was terminated; race where kubelet registered before the instance reached RUNNING.

Related errors


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