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
- Re-run the delete once the race settles; the wrapped error shows the HTTP status
- Confirm the group is empty with `openstack server group show <id>` then delete manually
- Check Nova policy.json/RBAC allows server group deletion for the user
- 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
- Re-read members immediately before delete to narrow the race window
- Serialize kops delete runs
- Grant the user compute:server_group delete RBAC
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
- could not delete instance %q: %v
- could not list server groups %v
- error building nova client: %v
- no decernable storage availability zone could be mapped to c
- error building nova client: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/de985ec438fdfc1b.
Report an issue: GitHub.