{"record":{"id":"cfee017f03d27065","repo":"kubernetes/kops","slug":"error-deleting-instancetemplate-s-w","errorCode":null,"errorMessage":"error deleting InstanceTemplate %s: %w","messagePattern":"error deleting InstanceTemplate (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/gce/wrappers.go","lineNumber":81,"sourceCode":"\n\treturn c.WaitForOp(op)\n}\n\n// DeleteInstanceTemplate deletes the specified InstanceTemplate (by URL) in GCE\nfunc DeleteInstanceTemplate(c GCECloud, selfLink string) error {\n\tklog.V(2).Infof(\"Deleting GCE InstanceTemplate %s\", selfLink)\n\tu, err := ParseGoogleCloudURL(selfLink)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\top, err := c.Compute().InstanceTemplates().Delete(u.Project, u.Name)\n\tif err != nil {\n\t\tif IsNotFound(err) {\n\t\t\tklog.Infof(\"instancetemplate not found, assuming deleted: %q\", selfLink)\n\t\t\treturn nil\n\t\t}\n\t\treturn fmt.Errorf(\"error deleting InstanceTemplate %s: %w\", selfLink, err)\n\t}\n\n\treturn c.WaitForOp(op)\n}\n\n// DeleteInstance deletes the specified instance (by URL) in GCE\nfunc DeleteInstance(c GCECloud, instanceSelfLink string) error {\n\tklog.V(2).Infof(\"Deleting GCE Instance %s\", instanceSelfLink)\n\tu, err := ParseGoogleCloudURL(instanceSelfLink)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\top, err := c.Compute().Instances().Delete(u.Project, u.Zone, u.Name)\n\tif err != nil {\n\t\tif IsNotFound(err) {\n\t\t\tklog.Infof(\"Instance not found, assuming deleted: %q\", instanceSelfLink)\n\t\t\treturn nil","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/gce/wrappers.go#L63-L99","documentation":"This error is returned by DeleteInstanceTemplate when InstanceTemplates().Delete(project, name) fails with anything other than 404 Not Found. It wraps the underlying googleapi error with the template's selfLink. GCE refuses to delete an instance template that is still referenced by an instance group manager, which is the most common cause. Missing templates are treated as already deleted.","triggerScenarios":"Calling DeleteInstanceTemplate (from DeleteCloudGroup teardown, after MIGs are deleted) where InstanceTemplates().Delete returns a non-NotFound error: the template is still in use by an existing/lingering InstanceGroupManager, IAM permission denial, invalid project, or transient API 5xx.","commonSituations":"Template-in-use errors because a previous teardown step (MIG deletion) partially failed or another cluster/tool still references the template; wrong project id in credentials so the template lookup/delete hits a different project; service account without compute.instanceTemplates.delete permission; stale template selfLinks pointing at already-deprecated resources.","solutions":["Read the wrapped cause: 'being used by' errors mean a MIG still references the template — delete that MIG first, then retry","Verify the credentials/project (GOOGLE_CREDENTIALS, GOOGLE_PROJECT) point at the project owning the template","Grant the service account compute.instanceTemplates.delete (via compute.admin or instanceAdmin roles)","Re-run `kops delete cluster --yes` — 404s are skipped, so it's safe to retry after fixing the blocker","As a last resort, delete the orphaned template manually with `gcloud compute instance-templates delete`"],"exampleFix":"// before: delete template without ensuring MIGs are gone\nerr := DeleteInstanceTemplate(cloud, tmplSelfLink)\n// after: ensure dependent MIGs removed first, tolerate not-found\nif err := DeleteMIGInstances(cloud, igm); err != nil {\n\treturn err\n}\nif err := DeleteInstanceGroupManager(cloud, igm); err != nil {\n\treturn err\n}\nif err := DeleteInstanceTemplate(cloud, tmplSelfLink); err != nil {\n\tif !isNotFound(err) {\n\t\treturn err\n\t}\n}","handlingStrategy":"validation","validationCode":"// Check no InstanceGroupManager still references the template before deleting it\niggs, err := cloud.Compute().InstanceGroupManagers().AggregatedList(project).Do()\nif err != nil {\n\treturn err\n}\nfor _, scoped := range iggs.Items {\n\tfor _, m := range scoped.InstanceGroupManagers {\n\t\tif m.InstanceTemplate == tmplSelfLink {\n\t\t\treturn fmt.Errorf(\"template %s still used by MIG %s\", tmplSelfLink, m.Name)\n\t\t}\n\t}\n}","typeGuard":"func isTemplateInUse(err error) bool {\n\tvar gerr *googleapi.Error\n\treturn errors.As(err, &gerr) && gerr.Code == 400 && strings.Contains(gerr.Message, \"being used\")\n}","tryCatchPattern":"err := gce.DeleteInstanceTemplate(cloud, selfLink)\nif err != nil {\n\tvar gerr *googleapi.Error\n\tif errors.As(err, &gerr) {\n\t\tif gerr.Code == 404 {\n\t\t\treturn nil // already deleted\n\t\t}\n\t\tif gerr.Code == 400 && strings.Contains(gerr.Message, \"being used\") {\n\t\t\t// delete dependent MIGs first, then retry\n\t\t}\n\t}\n\treturn err\n}","preventionTips":["Always delete MIGs (and resize to 0) before deleting instance templates","Verify GOOGLE_PROJECT/credentials match the project owning the template","Tag templates per cluster and clean up by tag so leftovers are identifiable","Check for other clusters/tools referencing the template before deleting"],"tags":["gce","compute-api","instance-template","deletion","resource-in-use"],"backgroundTag":"gce-api-delete-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}