kubernetes/kops · error

instance %s did not have Version set

Error message

instance %s did not have Version set

What it means

For MIG-owned instances, IdentifyNode reads the MIG member's currentVersion/Version to find the instance template that defines the group. If the ManagedInstance's Version field is nil (GCE did not populate it), the template cannot be resolved and identification fails.

Source

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

		}

		// We need to double-check the MIG configuration, in case created-by was changed
		migName := lastComponent(createdBy)

		mig, err := i.getMIG(zone, migName)
		if err != nil {
			return nil, err
		}

		// We now double check that the instance is indeed managed by the MIG
		// this can't be spoofed without GCE API access
		migMember, err := i.getManagedInstance(ctx, mig, instance.Id)
		if err != nil {
			return nil, err
		}

		if migMember.Version == nil {
			return nil, fmt.Errorf("instance %s did not have Version set", instance.Name)
		}

		instanceTemplate, err := i.getInstanceTemplate(lastComponent(migMember.Version.InstanceTemplate))
		if err != nil {
			return nil, err
		}

		igName = getMetadataValue(instanceTemplate.Properties.Metadata, MetadataKeyInstanceGroupName)
		if igName == "" {
			return nil, fmt.Errorf("ig name not set on instance template %s", instanceTemplate.Name)
		}
	}

	info := &nodeidentity.Info{}
	// info.InstanceID TODO: InstanceID is only used by the provider?

	tagToRole := make(map[string]kops.InstanceGroupRole)
	for _, role := range kops.AllInstanceGroupRoles {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Retry after the MIG update completes (TRANSIENT): check `gcloud compute instance-groups managed describe <mig> --zone <zone>` until all instances have a currentVersion.
  2. Recreate the MIG with a versioned instance template (gcloud compute instance-groups managed set-instance-template) so each member reports a Version.
  3. If the member is stuck, use recreate-instances on the MIG for that instance.
  4. Ensure the compute API version in use populates Version; upgrade kops/GCE client if using legacy fields.

Example fix

// before
if migMember.Version == nil { return nil, fmt.Errorf("instance %s did not have Version set", instance.Name) }
// after — retry with backoff while MIG settles
var tmpl string
err := wait.ExponentialBackoff(backoff, func() (bool, error) {
    m, err := i.getManagedInstance(ctx, mig, instance.Id)
    if err != nil { return false, nil }
    if m.Version == nil { return false, nil }
    tmpl = lastComponent(m.Version.InstanceTemplate)
    return true, nil
})
Defensive patterns

Strategy: retry

Validate before calling

migMember, err := getManagedInstance(ctx, mig, instance.Id)
if err == nil && migMember.Version == nil {
    return fmt.Errorf("MIG member %d has no version yet; MIG update in progress, retry", instance.Id)
}

Type guard

func hasVersion(m *compute.ManagedInstance) bool {
    return m != nil && m.Version != nil && m.Version.InstanceTemplate != ""
}

Try / catch

info, err := identifier.IdentifyNode(ctx, node)
if err != nil && strings.Contains(err.Error(), "did not have Version set") {
    // transient during MIG rolling updates: retry with backoff
    return requeueWithBackoff(err)
}

Prevention

When it happens

Trigger: getManagedInstance returns a compute.ManagedInstance whose Version is nil — seen with MIGs created by very old API versions, MIGs mid-update where targetDistribution state is odd, or instances being recreated/abandoned during a MIG update.

Common situations: MIG in the middle of an autohealing/rolling-update action; MIG created without versioned templates (legacy instanceTemplate-only MIGs); transient GCE API responses during instance recreation.

Related errors


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