kubernetes/kops · error

could not delete server group %q: %v

Error message

could not delete server group %q: %v

What it means

Wrapped error returned when deleting an empty OpenStack server group fails during instance-group teardown. kOps only deletes a server group with zero members; if Nova rejects DeleteServerGroup(sg.ID), the cleanup aborts with the group ID and cause.

Source

Thrown at upup/pkg/fi/cloudup/openstack/cloud.go:684

	if err != nil {
		return err
	}

	sgName := g.InstanceGroup.Name
	if name, ok := g.InstanceGroup.Annotations[OS_ANNOTATION+SERVER_GROUP_NAME]; ok {
		sgName = name
	}
	sgs, err := c.ListServerGroups(servergroups.ListOpts{})
	if err != nil {
		return fmt.Errorf("could not list server groups %v", err)
	}

	for _, sg := range sgs {
		if fmt.Sprintf("%s-%s", cluster.Name, sgName) == sg.Name {
			if len(sg.Members) == 0 {
				err = c.DeleteServerGroup(sg.ID)
				if err != nil {
					return fmt.Errorf("could not delete server group %q: %v", sg.ID, err)
				}
			} else {
				klog.Infof("Server group %q still has members (IDs: %s), delete not executed", sg.ID, strings.Join(sg.Members, ", "))
			}
			break
		}
	}
	return nil
}

func (c *openstackCloud) GetCloudGroups(cluster *kops.Cluster, instancegroups []*kops.InstanceGroup, warnUnmatched bool, nodes []v1.Node) (map[string]*cloudinstances.CloudInstanceGroup, error) {
	return getCloudGroups(c, cluster, instancegroups, warnUnmatched, nodes)
}

func getCloudGroups(c OpenstackCloud, cluster *kops.Cluster, instancegroups []*kops.InstanceGroup, warnUnmatched bool, nodes []v1.Node) (map[string]*cloudinstances.CloudInstanceGroup, error) {
	nodeMap := cloudinstances.GetNodeMap(nodes, cluster)
	groups := make(map[string]*cloudinstances.CloudInstanceGroup)
	for _, ig := range instancegroups {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Re-run the delete once the race settles; the wrapped error shows the HTTP status
  2. Confirm the group is empty with `openstack server group show <id>` then delete manually
  3. Check Nova policy.json/RBAC allows server group deletion for the user
  4. If 404, the group is already gone and cleanup effectively succeeded
Defensive patterns

Strategy: retry

Validate before calling

sg, err := getServerGroupByName(cluster.Name, sgName)
if err == nil && len(sg.Members) > 0 { return fmt.Errorf("server group %s still has members", sg.ID) }

Try / catch

if err := c.DeleteServerGroup(sg.ID); err != nil {
    var gErr gophercloud.ErrUnexpectedResponseCode
    if errors.As(err, &gErr) && (gErr.Actual == 404 || gErr.Actual == 409) { /* re-check and retry */ }
    return fmt.Errorf("could not delete server group %q: %v", sg.ID, err)
}

Prevention

When it happens

Trigger: c.DeleteServerGroup(sg.ID) returns an error, typically 404 (group already deleted), 409 (members appeared between listing and delete), or permission/endpoint failure.

Common situations: Race where an instance was scheduled into the group after the member check; group deleted concurrently by another kops run or operator; insufficient RBAC policy on the compute API.

Related errors


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