kubernetes/kops · error

error deleting security group: %v

Error message

error deleting security group: %v

What it means

This error is returned by deleteSecurityGroup when the Neutron security-group Delete API fails with an error other than 404 Not Found, inside the deleteBackoff retry loop. A 404 is deliberately treated as success (already deleted), so this error signals a real failure: the group is still in use, permissions are missing, or the API is unreachable. The error is retried per backoff policy and then propagated.

Source

Thrown at upup/pkg/fi/cloudup/openstack/security_group.go:143

	})
	if err != nil {
		return rule, err
	} else if done {
		return rule, nil
	} else {
		return rule, wait.ErrWaitTimeout
	}
}

func (c *openstackCloud) DeleteSecurityGroup(sgID string) error {
	return deleteSecurityGroup(c, sgID)
}

func deleteSecurityGroup(c OpenstackCloud, sgID string) error {
	done, err := vfs.RetryWithBackoff(deleteBackoff, func() (bool, error) {
		err := sg.Delete(context.TODO(), c.NetworkingClient(), sgID).ExtractErr()
		if err != nil && !isNotFound(err) {
			return false, fmt.Errorf("error deleting security group: %v", err)
		}
		if isNotFound(err) {
			return true, nil
		}
		return false, nil
	})
	if err != nil {
		return err
	} else if done {
		return nil
	} else {
		return wait.ErrWaitTimeout
	}
}

func (c *openstackCloud) DeleteSecurityGroupRule(ruleID string) error {
	return deleteSecurityGroupRule(c, ruleID)
}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check the wrapped status: on 409 delete the group's rules/members first (deleteSecurityGroupRule) or wait for instances to detach
  2. Never delete the project's default security group; skip it explicitly
  3. On 401/403 refresh credentials and confirm the project/region in the cloud config
  4. If transient (5xx/429), let the retry backoff handle it or rerun teardown

Example fix

// before: delete rules implicitly via group delete
err := sg.Delete(context.TODO(), c.NetworkingClient(), sgID).ExtractErr()
// after: remove dependent rules first
rules, err := listSecurityGroupRules(c, sgr.ListOpts{SecurityGroupID: sgID})
if err != nil { return err }
for _, r := range rules {
	if err := deleteSecurityGroupRule(c, r.ID); err != nil { return err }
}
err = sg.Delete(context.TODO(), c.NetworkingClient(), sgID).ExtractErr()
Defensive patterns

Strategy: try-catch

Validate before calling

sg, err := groups.Get(ctx, cloud.NetworkingClient(), sgID).Extract()
if err != nil {
	if gophercloud.ResponseCodeIs(err, 404) { return nil } // already gone
	return err
}
if sg.Name == "default" {
	return fmt.Errorf("refusing to delete the default security group %q", sgID)
}

Type guard

func isNotFoundErr(err error) bool {
	var nf gophercloud.ErrDefault404
	return errors.As(err, &nf)
}

Try / catch

err := deleteSecurityGroup(c, sgID)
if err != nil {
	if isNotFoundErr(err) { return nil }
	if strings.Contains(err.Error(), "409") {
		// delete child rules / wait for detachment, then retry once
	}
	return fmt.Errorf("deleting sg %s: %w", sgID, err)
}

Prevention

When it happens

Trigger: sg.Delete(...).ExtractErr() returns an error where isNotFound(err) is false — most commonly HTTP 409 because the security group still has members/rules or is the default group, or 403/401 auth/RBAC failures.

Common situations: Trying to delete a security group that still has interfaces attached or rules referencing it, attempting to delete the project's default security group, teardown running with stale or insufficient credentials.

Related errors


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