kubernetes/kops · warning

found multiple SecurityGroups with ID %q

Error message

found multiple SecurityGroups with ID %q

What it means

In DeleteSecurityGroup (pkg/resources/aws/securitygroup.go:57), after DescribeSecurityGroups by ID the code asserts exactly one group is returned. This error means the API returned more than one security group for a single GroupId filter — logically impossible under normal EC2 behavior, so it indicates an unexpected/inconsistent response.

Source

Thrown at pkg/resources/aws/securitygroup.go:57

	// TODO: Move to a "pre-execute" phase?
	{
		request := &ec2.DescribeSecurityGroupsInput{
			GroupIds: []string{id},
		}
		response, err := c.EC2().DescribeSecurityGroups(ctx, request)
		if err != nil {
			if awsup.AWSErrorCode(err) == "InvalidGroup.NotFound" {
				klog.V(2).Infof("Got InvalidGroup.NotFound error describing SecurityGroup %q; will treat as already-deleted", id)
				return nil
			}
			return fmt.Errorf("error describing SecurityGroup %q: %v", id, err)
		}

		if len(response.SecurityGroups) == 0 {
			return nil
		}
		if len(response.SecurityGroups) != 1 {
			return fmt.Errorf("found multiple SecurityGroups with ID %q", id)
		}

		ruleReqest := &ec2.DescribeSecurityGroupRulesInput{
			Filters: []ec2types.Filter{
				{Name: aws.String("group-id"), Values: []string{id}},
			},
		}
		ruleResp, err := c.EC2().DescribeSecurityGroupRules(ctx, ruleReqest)
		if err != nil {
			if awsup.AWSErrorCode(err) == "InvalidGroup.NotFound" {
				klog.V(2).Infof("Got InvalidGroup.NotFound error describing rules for SecurityGroup %q; will treat as already-deleted", id)
				return nil
			}
			return fmt.Errorf("error describing SecurityGroup rules %q: %v", id, err)
		}

		ingressRuleIDs := make([]string, 0)
		for _, rule := range ruleResp.SecurityGroupRules {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Confirm you are hitting real AWS EC2, not a compatible/proxied endpoint.
  2. Re-run the delete; transient inconsistency usually does not reproduce.
  3. Check for API-mocking middleware (SDK interceptors, custom endpoint resolvers) distorting the response.
  4. Report upstream (kops issue) if reproducible against real AWS, including SDK version.
Defensive patterns

Strategy: validation

Validate before calling

// sanity-check the EC2 endpoint before relying on responses
if strings.Contains(ec2Endpoint, "mock") || ec2Endpoint == "" && customResolverSet {
    return fmt.Errorf("unexpected EC2 endpoint %q", ec2Endpoint)
}

Type guard

func expectSingleSG(resp *ec2.DescribeSecurityGroupsOutput) (ec2types.SecurityGroup, bool) {
    if resp == nil || len(resp.SecurityGroups) != 1 { return ec2types.SecurityGroup{}, false }
    return resp.SecurityGroups[0], true
}

Try / catch

if err := DeleteSecurityGroup(cloud, r); err != nil {
    if strings.Contains(err.Error(), "found multiple SecurityGroups") {
        klog.Errorf("EC2 response invariant broken; check endpoint/proxy: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: EC2 returning len(response.SecurityGroups) != 1 (and != 0) for a DescribeSecurityGroups call with a single GroupId — e.g. mocked/intercepted API responses, proxies altering results, or future API semantic changes.

Common situations: Very rare in practice; seen in tests with faulty mocks, corporate API intermediaries mutating responses, or bespoke EC2-compatible endpoints (e.g. some on-prem/compatible clouds) that do not honor GroupId uniqueness.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/4af5dbd4346374e0. Report an issue: GitHub.