{"record":{"id":"16338700281f85c3","repo":"kubernetes/kops","slug":"error-deleting-serviceaccount-s-v","errorCode":null,"errorMessage":"error deleting ServiceAccount %s: %v","messagePattern":"error deleting ServiceAccount (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/resources/gce/gce.go","lineNumber":1059,"sourceCode":"\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\treturn resourceTrackers, nil\n}\n\nfunc deleteServiceAccount(cloud fi.Cloud, r *resources.Resource) error {\n\tc := cloud.(gce.GCECloud)\n\to := r.Obj.(*iam.ServiceAccount)\n\n\tklog.V(2).Infof(\"deleting GCE ServiceAccount %s\", o.Name)\n\t_, err := c.IAM().ServiceAccounts().Delete(o.Name)\n\tif err != nil {\n\t\tif gce.IsNotFound(err) {\n\t\t\tklog.Infof(\"ServiceAccount not found, assuming deleted: %q\", o.Name)\n\t\t\treturn nil\n\t\t}\n\t\treturn fmt.Errorf(\"error deleting ServiceAccount %s: %v\", o.Name, err)\n\t}\n\treturn nil\n}\n\n// containsOnlyListedIGMs returns true if all the given backend service's backends\n// are contained in the provided list of IGM resources.\nfunc containsOnlyListedIGMs(svc *compute.BackendService, igms []*resources.Resource) bool {\n\tif len(svc.Backends) == 0 {\n\t\treturn false\n\t}\n\n\tfor _, be := range svc.Backends {\n\t\tlisted := false\n\t\tfor _, igm := range igms {\n\t\t\t// NOTE: this should be sufficient / strict enough since IGM names include the cluster\n\t\t\t// that they are part of, but revisit if naming conventions change.\n\t\t\tif strings.HasSuffix(be.Group, \"/\"+igm.Name) {\n\t\t\t\tlisted = true","sourceCodeStart":1041,"sourceCodeEnd":1077,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/resources/gce/gce.go#L1041-L1077","documentation":"Thrown by deleteServiceAccount when IAM().ServiceAccounts().Delete fails with any error other than NotFound. One of the cluster's generated service accounts could not be removed during cluster teardown.","triggerScenarios":"ServiceAccounts().Delete(o.Name) returns 403 (caller lacks iam.serviceAccounts.delete, e.g. missing roles/iam.serviceAccountAdmin), 404-adjacent preconditions, 400 because the SA has user-managed keys or is disabled/deleted state conflicts, or a transient IAM API error.","commonSituations":"kops credentials lack the Service Account Admin role while having compute rights; SA still has active bindings/keys that some org policies require clearing first; IAM API throttling during teardown.","solutions":["Grant roles/iam.serviceAccountAdmin to the kops service account.","Check the wrapped error; if it mentions keys/bindings, remove them (`gcloud iam service-accounts keys delete`, `gcloud projects remove-iam-policy-binding`).","Retry on 429/5xx; NotFound is already handled as success so re-running is safe.","Clean up leftovers manually: `gcloud iam service-accounts delete EMAIL`."],"exampleFix":"// before\nreturn fmt.Errorf(\"error deleting ServiceAccount %s: %v\", o.Name, err)\n// after\nreturn fmt.Errorf(\"error deleting ServiceAccount %s: %w\", o.Name, err)","handlingStrategy":"try-catch","validationCode":"// test delete permission without deleting: check roles via testIamPermissions\nok, err := iamClient.Projects.ServiceAccounts.TestIamPermissions(saName, &iamapi.TestIamPermissionsRequest{Permissions: []string{\"iam.serviceAccounts.delete\"}}).Do()","typeGuard":"func isIAMPermissionError(err error) bool {\n\tge, ok := err.(*googleapi.Error)\n\treturn ok && ge.Code == 403\n}","tryCatchPattern":"_, err := c.IAM().ServiceAccounts().Delete(o.Name)\nif err != nil {\n\tif gce.IsNotFound(err) {\n\t\treturn nil\n\t}\n\tvar ge *googleapi.Error\n\tif errors.As(err, &ge) && ge.Code == 403 {\n\t\tklog.Warningf(\"missing iam.serviceAccounts.delete for %s\", o.Name)\n\t}\n\treturn fmt.Errorf(\"error deleting ServiceAccount %s: %w\", o.Name, err)\n}","preventionTips":["Grant roles/iam.serviceAccountAdmin for full cluster teardown.","Remove SA keys and IAM bindings before deleting (some org policies require it).","Verify cleanup with `gcloud iam service-accounts list` after deletion."],"tags":["gce","iam","service-account","deletion"],"backgroundTag":"gcp-iam-permission-denied","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"}