{"record":{"id":"7db352dc33a293f2","repo":"kubernetes/kops","slug":"error-deleting-iam-role-v","errorCode":null,"errorMessage":"error deleting IAM role: %v","messagePattern":"error deleting IAM role: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/awstasks/iamrole.go","lineNumber":231,"sourceCode":"\n\t\t// Detach Managed Policies\n\t\tfor _, policy := range attachedPolicies {\n\t\t\tklog.V(2).Infof(\"Detaching IAM role policy %v\", policy)\n\t\t\trequest := &iam.DetachRolePolicyInput{\n\t\t\t\tRoleName:  a.Name,\n\t\t\t\tPolicyArn: policy.PolicyArn,\n\t\t\t}\n\t\t\t_, err := t.Cloud.IAM().DetachRolePolicy(ctx, request)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"error detaching IAM role policy %q: %v\", *policy.PolicyArn, err)\n\t\t\t}\n\t\t}\n\n\t\trequest := &iam.DeleteRoleInput{\n\t\t\tRoleName: a.Name,\n\t\t}\n\t\tif _, err := t.Cloud.IAM().DeleteRole(ctx, request); err != nil {\n\t\t\treturn fmt.Errorf(\"error deleting IAM role: %v\", err)\n\t\t}\n\t\treturn nil\n\t}\n\n\tpolicy, err := fi.ResourceAsString(e.RolePolicyDocument)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error rendering RolePolicyDocument: %v\", err)\n\t}\n\n\tif a == nil {\n\t\tklog.V(2).Infof(\"Creating IAMRole with Name:%q\", *e.Name)\n\n\t\trequest := &iam.CreateRoleInput{}\n\t\trequest.AssumeRolePolicyDocument = aws.String(policy)\n\t\trequest.RoleName = e.Name\n\t\trequest.Tags = mapToIAMTags(e.Tags)\n\n\t\tif e.PermissionsBoundary != nil {","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/awstasks/iamrole.go#L213-L249","documentation":"In IAMRole.RenderAWS, after detaching policies, kOps calls IAM DeleteRole to remove the role. Any error from the AWS API is wrapped as 'error deleting IAM role: %v', aborting the deletion of that task. The wrapped error carries the raw AWS SDK message.","triggerScenarios":"DeleteRole returns NoSuchEntity (role vanished concurrently), DeleteConflict (role still bound to an instance profile, or policies remain attached), AccessDenied (missing iam:DeleteRole), or throttling during bulk cluster deletion.","commonSituations":"Tearing down a cluster where an autoscaling group or node still references the role; external controllers recreated attached policies between detach and delete; IAM rate limiting when deleting dozens of roles at once; credentials scoped too narrowly.","solutions":["Inspect the wrapped AWS error: for DeleteConflict remove remaining instance-profile/policy associations and retry","For NoSuchEntity, re-run kops delete cluster so the task state refreshes and the role is marked gone","Add iam:DeleteRole and iam:ListInstanceProfilesForRole to the credentials' policy","Retry later with backoff if the error indicates throttling (RequestLimitExceeded)"],"exampleFix":"// before\n_, err := t.Cloud.IAM().DeleteRole(ctx, request)\n\n// after: tolerate already-deleted roles\nif _, err := t.Cloud.IAM().DeleteRole(ctx, request); err != nil {\n    var nfe *iam.NoSuchEntityException\n    if !errors.As(err, &nfe) {\n        return fmt.Errorf(\"error deleting IAM role: %v\", err)\n    }\n}","handlingStrategy":"try-catch","validationCode":"attached, _ := iamClient.ListAttachedRolePolicies(&iam.ListAttachedRolePoliciesInput{RoleName: &roleName})\nprofiles, _ := iamClient.ListInstanceProfilesForRole(&iam.ListInstanceProfilesForRoleInput{RoleName: &roleName})\nif len(attached.AttachedPolicies) > 0 || len(profiles.InstanceProfiles) > 0 {\n    return fmt.Errorf(\"role %s is not deletable yet\", roleName)\n}","typeGuard":null,"tryCatchPattern":"_, err := t.Cloud.IAM().DeleteRole(ctx, req)\nif err != nil {\n    var nfe *iam.NoSuchEntityException\n    if errors.As(err, &nfe) { return nil } // already gone\n    if strings.Contains(err.Error(), \"DeleteConflict\") { /* clean associations, retry */ }\n    return err\n}","preventionTips":["Detach all policies and instance profiles before deleting a role","Never share kOps-managed roles with other systems","Add a retry with backoff for throttling during mass deletions","Verify iam:DeleteRole permission in restricted environments"],"tags":["aws","iam","go","kops"],"backgroundTag":"aws-iam-delete-conflict","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"}