{"record":{"id":"b887eff388081f11","repo":"kubernetes/kops","slug":"instance-s-did-not-have-version-set","errorCode":null,"errorMessage":"instance %s did not have Version set","messagePattern":"instance (.+?) did not have Version set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/nodeidentity/gce/identify.go","lineNumber":167,"sourceCode":"\t\t}\n\n\t\t// We need to double-check the MIG configuration, in case created-by was changed\n\t\tmigName := lastComponent(createdBy)\n\n\t\tmig, err := i.getMIG(zone, migName)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\t// We now double check that the instance is indeed managed by the MIG\n\t\t// this can't be spoofed without GCE API access\n\t\tmigMember, err := i.getManagedInstance(ctx, mig, instance.Id)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tif migMember.Version == nil {\n\t\t\treturn nil, fmt.Errorf(\"instance %s did not have Version set\", instance.Name)\n\t\t}\n\n\t\tinstanceTemplate, err := i.getInstanceTemplate(lastComponent(migMember.Version.InstanceTemplate))\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\tigName = getMetadataValue(instanceTemplate.Properties.Metadata, MetadataKeyInstanceGroupName)\n\t\tif igName == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"ig name not set on instance template %s\", instanceTemplate.Name)\n\t\t}\n\t}\n\n\tinfo := &nodeidentity.Info{}\n\t// info.InstanceID TODO: InstanceID is only used by the provider?\n\n\ttagToRole := make(map[string]kops.InstanceGroupRole)\n\tfor _, role := range kops.AllInstanceGroupRoles {","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/nodeidentity/gce/identify.go#L149-L185","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Retry after the MIG update completes (TRANSIENT): check `gcloud compute instance-groups managed describe <mig> --zone <zone>` until all instances have a currentVersion.","Recreate the MIG with a versioned instance template (gcloud compute instance-groups managed set-instance-template) so each member reports a Version.","If the member is stuck, use recreate-instances on the MIG for that instance.","Ensure the compute API version in use populates Version; upgrade kops/GCE client if using legacy fields."],"exampleFix":"// before\nif migMember.Version == nil { return nil, fmt.Errorf(\"instance %s did not have Version set\", instance.Name) }\n// after — retry with backoff while MIG settles\nvar tmpl string\nerr := wait.ExponentialBackoff(backoff, func() (bool, error) {\n    m, err := i.getManagedInstance(ctx, mig, instance.Id)\n    if err != nil { return false, nil }\n    if m.Version == nil { return false, nil }\n    tmpl = lastComponent(m.Version.InstanceTemplate)\n    return true, nil\n})","handlingStrategy":"retry","validationCode":"migMember, err := getManagedInstance(ctx, mig, instance.Id)\nif err == nil && migMember.Version == nil {\n    return fmt.Errorf(\"MIG member %d has no version yet; MIG update in progress, retry\", instance.Id)\n}","typeGuard":"func hasVersion(m *compute.ManagedInstance) bool {\n    return m != nil && m.Version != nil && m.Version.InstanceTemplate != \"\"\n}","tryCatchPattern":"info, err := identifier.IdentifyNode(ctx, node)\nif err != nil && strings.Contains(err.Error(), \"did not have Version set\") {\n    // transient during MIG rolling updates: retry with backoff\n    return requeueWithBackoff(err)\n}","preventionTips":["Avoid identifying nodes while kops rolling-update is actively replacing them.","Use versioned instance templates on all MIGs (not legacy template-only MIGs).","Add backoff/retry around identification.","Monitor MIG status until stable before running identification-dependent jobs."],"tags":["gce","mig","node-identity","instance-template","transient"],"backgroundTag":"mig-version-missing","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}