{"record":{"id":"00c78432b22d6ca7","repo":"kubernetes/kops","slug":"cannot-revoke-ingress-for-id-q-with-rule-ids-v","errorCode":null,"errorMessage":"cannot revoke ingress for ID %q with rule IDs %v: %v","messagePattern":"cannot revoke ingress for ID %q with rule IDs (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/resources/aws/securitygroup.go","lineNumber":88,"sourceCode":"\t\t\t}\n\t\t\treturn fmt.Errorf(\"error describing SecurityGroup rules %q: %v\", id, err)\n\t\t}\n\n\t\tingressRuleIDs := make([]string, 0)\n\t\tfor _, rule := range ruleResp.SecurityGroupRules {\n\t\t\tif !aws.ToBool(rule.IsEgress) {\n\t\t\t\tingressRuleIDs = append(ingressRuleIDs, aws.ToString(rule.SecurityGroupRuleId))\n\t\t\t}\n\t\t}\n\n\t\tif len(ingressRuleIDs) != 0 {\n\t\t\trevoke := &ec2.RevokeSecurityGroupIngressInput{\n\t\t\t\tGroupId:              aws.String(id),\n\t\t\t\tSecurityGroupRuleIds: ingressRuleIDs,\n\t\t\t}\n\t\t\t_, err = c.EC2().RevokeSecurityGroupIngress(ctx, revoke)\n\t\t\tif err != nil {\n\t\t\t\treturn fmt.Errorf(\"cannot revoke ingress for ID %q with rule IDs %v: %v\", id, ingressRuleIDs, err)\n\t\t\t}\n\t\t}\n\t}\n\n\t{\n\t\tklog.V(2).Infof(\"Deleting EC2 SecurityGroup %q\", id)\n\t\trequest := &ec2.DeleteSecurityGroupInput{\n\t\t\tGroupId: &id,\n\t\t}\n\t\t_, err := c.EC2().DeleteSecurityGroup(ctx, request)\n\t\tif err != nil {\n\t\t\tif IsDependencyViolation(err) {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\treturn fmt.Errorf(\"error deleting SecurityGroup %q: %v\", id, err)\n\t\t}\n\t}\n\treturn nil","sourceCodeStart":70,"sourceCodeEnd":106,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/resources/aws/securitygroup.go#L70-L106","documentation":"In DeleteSecurityGroup (pkg/resources/aws/securitygroup.go:88), the enumerated ingress rule IDs are revoked via RevokeSecurityGroupIngress before deleting the group. This error wraps the revoke failure and includes the group ID and the specific rule IDs attempted. It means the SG's ingress rules could not be cleared, blocking subsequent deletion of inter-dependent groups.","triggerScenarios":"RevokeSecurityGroupIngress with GroupId + SecurityGroupRuleIds failing: InvalidGroup.NotFound (group/rule vanished concurrently), InvalidPermission.NotFound (rule already removed), UnauthorizedOperation (missing ec2:RevokeSecurityGroupIngress), throttling, or stale rule IDs from a prior describe.","commonSituations":"Concurrent deletion (another kops run or controller removing rules) causing stale rule IDs; IAM missing RevokeSecurityGroupIngress; default-VPC groups referenced by other groups causing dependency errors during parallel teardown.","solutions":["Re-describe the SG's rules and retry the revoke with fresh rule IDs (stale-ID race).","Grant ec2:RevokeSecurityGroupIngress in the IAM policy.","If rules/group are already gone, treat as success and proceed to DeleteSecurityGroup.","Retry on throttling; serialize deletion of interdependent security groups."],"exampleFix":"// before\n_, err = c.EC2().RevokeSecurityGroupIngress(ctx, revoke)\nif err != nil {\n    return fmt.Errorf(\"cannot revoke ingress for ID %q with rule IDs %v: %v\", id, ingressRuleIDs, err)\n}\n// after\n_, err = c.EC2().RevokeSecurityGroupIngress(ctx, revoke)\nif err != nil {\n    code := awsup.AWSErrorCode(err)\n    if code == \"InvalidGroup.NotFound\" || code == \"InvalidPermission.NotFound\" {\n        klog.V(2).Infof(\"Ingress rules for %q already revoked\", id)\n    } else {\n        return fmt.Errorf(\"cannot revoke ingress for ID %q with rule IDs %v: %w\", id, ingressRuleIDs, err)\n    }\n}","handlingStrategy":"retry","validationCode":"// refresh rule IDs immediately before revoking\ndesc, err := ec2Client.DescribeSecurityGroupRules(ctx, &ec2.DescribeSecurityGroupRulesInput{\n    Filters: []ec2types.Filter{{Name: aws.String(\"group-id\"), Values: []string{id}}},\n})\nif err != nil { return err }\nif len(desc.SecurityGroupRules) == 0 { return nil } // nothing to revoke","typeGuard":"func isRevocableRace(err error) bool {\n    c := awsup.AWSErrorCode(err)\n    return c == \"InvalidGroup.NotFound\" || c == \"InvalidPermission.NotFound\" || c == \"InvalidRule.NotFound\"\n}","tryCatchPattern":"_, err := ec2Client.RevokeSecurityGroupIngress(ctx, revoke)\nif err != nil {\n    if isRevocableRace(err) { return nil } // already gone\n    if isThrottling(err) { /* retry with backoff */ }\n    return fmt.Errorf(\"cannot revoke ingress for %q: %w\", id, err)\n}","preventionTips":["Re-describe rules right before revoking to avoid stale-ID races.","Run only one kops delete against a cluster at a time.","Grant ec2:RevokeSecurityGroupIngress in automation roles.","Use exponential backoff for throttling errors."],"tags":["aws","ec2","security-group","ingress","revoke"],"backgroundTag":"aws-api-mutation-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"}