{"record":{"id":"c1fdaa93a36ccbaf","repo":"kubernetes/kops","slug":"error-deleting-instancegroupmanager-s-w","errorCode":null,"errorMessage":"error deleting InstanceGroupManager %s: %w","messagePattern":"error deleting InstanceGroupManager (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/gce/wrappers.go","lineNumber":41,"sourceCode":"\tcompute \"google.golang.org/api/compute/v1\"\n\t\"k8s.io/klog/v2\"\n)\n\n// DeleteInstanceGroupManager deletes the specified InstanceGroupManager in GCE\nfunc DeleteInstanceGroupManager(c GCECloud, t *compute.InstanceGroupManager) error {\n\tklog.V(2).Infof(\"Deleting GCE InstanceGroupManager %s\", t.SelfLink)\n\tu, err := ParseGoogleCloudURL(t.SelfLink)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\top, err := c.Compute().InstanceGroupManagers().Delete(u.Project, u.Zone, u.Name)\n\tif err != nil {\n\t\tif IsNotFound(err) {\n\t\t\tklog.Infof(\"InstanceGroupManager not found, assuming deleted: %q\", t.SelfLink)\n\t\t\treturn nil\n\t\t}\n\t\treturn fmt.Errorf(\"error deleting InstanceGroupManager %s: %w\", t.SelfLink, err)\n\t}\n\n\treturn c.WaitForOp(op)\n}\n\n// DeleteMIGInstances deletes the instances in the MIG in GCE\nfunc DeleteMIGInstances(c GCECloud, t *compute.InstanceGroupManager) error {\n\tklog.V(2).Infof(\"Deleting Instances in InstanceGroupManager %s\", t.SelfLink)\n\tu, err := ParseGoogleCloudURL(t.SelfLink)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\top, err := c.Compute().InstanceGroupManagers().Resize(u.Project, u.Zone, u.Name, 0)\n\tif err != nil {\n\t\tif IsNotFound(err) {\n\t\t\tklog.Infof(\"InstanceGroupManager not found, assuming deleted: %q\", t.SelfLink)\n\t\t\treturn nil","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/gce/wrappers.go#L23-L59","documentation":"This error is returned by DeleteInstanceGroupManager in kOps' GCE cloud provider when the Compute API call InstanceGroupManagers().Delete fails with anything other than a 404 Not Found. It wraps the underlying googleapi error (quota, permission, dependency, or operation conflict) together with the MIG's selfLink so the failing resource is identifiable. A not-found MIG is deliberately treated as already-deleted success and does NOT produce this error.","triggerScenarios":"Calling DeleteInstanceGroupManager (via DeleteCloudGroup during cluster/instance-group teardown) where InstanceGroupManagers().Delete(project, zone, name) returns a non-NotFound error: e.g. the MIG still has instances being deleted by another operation, insufficient compute.instanceGroupManagerManager permissions, project/quota issues, or transient API 5xx errors.","commonSituations":"kOps cluster deletion racing with a GCE deletion operation already in flight on the same MIG ('Failed to delete instance group manager: operation already in progress'); service account lacking compute.instanceGroupManagerAdmin or compute.instanceAdmin roles; stale MIG selfLinks after a previous partial delete; regional-vs-zonal MIG mismatches; intermittent GCE API 500/503s during large cluster teardown.","solutions":["Check the wrapped googleapi error (%v of the cause) for the exact GCE error code and failed operation name in the message","Ensure the service account has compute.instanceGroupManagerAdmin/compute.instanceAdmin IAM roles for the project","Retry the kOps delete after in-flight GCE operations on the MIG complete (kops delete cluster --yes is idempotent; already-deleted MIGs are skipped)","If the MIG is stuck, inspect it with `gcloud compute instance-groups managed describe` and delete any blocking operations, then re-run","For repeated 5xx/quota errors, back off and retry later or raise quota for the region"],"exampleFix":"// before: non-idempotent manual teardown that hard-fails on transient errors\nif err := DeleteInstanceGroupManager(cloud, igm); err != nil {\n\treturn err\n}\n// after: retry transient failures; 404 already treated as success\nvar lastErr error\nfor i := 0; i < 3; i++ {\n\tlastErr = DeleteInstanceGroupManager(cloud, igm)\n\tif lastErr == nil {\n\t\treturn nil\n\t}\n\tif isRetryableGCEError(lastErr) {\n\t\ttime.Sleep(time.Duration(1<<i) * time.Second)\n\t\tcontinue\n\t}\n\treturn lastErr\n}\nreturn lastErr","handlingStrategy":"retry","validationCode":"// Before tearing down, check the MIG exists and no op is in flight\nigm, err := cloud.Compute().InstanceGroupManagers().Get(project, zone, name)\nif err != nil {\n\tif isNotFound(err) {\n\t\treturn nil // already deleted, skip\n\t}\n\treturn err\n}\nif igm.Status != nil && len(igm.Status.PendingActions) > 0 {\n\treturn fmt.Errorf(\"MIG %s has pending actions; retry later\", name)\n}","typeGuard":"// Unwrap and classify the googleapi error\nfunc isGCEPreconditionOrConflict(err error) bool {\n\tvar gerr *googleapi.Error\n\tif errors.As(err, &gerr) {\n\t\treturn gerr.Code == 409 || gerr.Code == 412 || gerr.Code == 429\n\t}\n\treturn false\n}","tryCatchPattern":"// In Go, pattern-match the wrapped error rather than try/catch\nerr := gce.DeleteInstanceGroupManager(cloud, igm)\nif err != nil {\n\tvar gerr *googleapi.Error\n\tif errors.As(err, &gerr) && gerr.Code == 409 {\n\t\t// concurrent op; retry with backoff\n\t} else if !isNotFound(err) {\n\t\treturn fmt.Errorf(\"deleting MIG %s: %w\", igm.SelfLink, err)\n\t}\n}","preventionTips":["Only run one teardown at a time per cluster; avoid overlapping kops delete with manual gcloud deletes","Ensure the service account has full compute.instanceGroupManagerAdmin IAM before teardown","Make teardown resumable: treat 404 as success (as kOps does) and re-run on partial failure","Check MIG status/pending actions before issuing delete operations"],"tags":["gce","compute-api","instance-group-manager","deletion","wrapped-error"],"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-12T07:17:12.445Z"}