kubernetes/kops · error

error deleting server group: %v

Error message

error deleting server group: %v

What it means

deleteServerGroup calls the Nova servergroups.Delete API. Errors are wrapped as "error deleting server group: %v" unless the error is a 404 (isNotFound), which is treated as success because the desired end state (group gone) is already reached. After deleteBackoff retries are exhausted, the wrapped error propagates.

Source

Thrown at upup/pkg/fi/cloudup/openstack/server_group.go:147

			klog.Warningf("Unable to find fixed ip for %s: %v", instance.Name, err)
		}

		cm.PrivateIP = ip
		cm.Roles = []string{instance.Metadata["KopsRole"]}
		cm.State = cloudinstances.State(instance.Status)
	}
	return cg, nil
}

func (c *openstackCloud) DeleteServerGroup(groupID string) error {
	return deleteServerGroup(c, groupID)
}

func deleteServerGroup(c OpenstackCloud, groupID string) error {
	done, err := vfs.RetryWithBackoff(deleteBackoff, func() (bool, error) {
		err := servergroups.Delete(context.TODO(), c.ComputeClient(), groupID).ExtractErr()
		if err != nil && !isNotFound(err) {
			return false, fmt.Errorf("error deleting server 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
	}
}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Delete remaining instances in the server group first ('openstack server list --group <group-id>' then delete them), then retry.
  2. Check auth/roles: ensure the credentials own the server group and have compute:os-server-groups delete permissions.
  3. Read the wrapped HTTP status: 409 -> wait for in-flight operations on the group to finish; 401 -> refresh credentials.
  4. If the group is already gone, ignore — isNotFound maps it to success; verify with 'openstack server group show <group-id>'.
  5. Retry after transient nova-api failures; the internal backoff already retries persistent 5xx.

Example fix

// before: deleting group while instances still exist -> 403/409
if err := cloud.DeleteServerGroup(group.ID); err != nil { return err }
// after: drain members first
for _, inst := range membersOfGroup(group.ID) {
	if err := deleteServer(instance.ID); err != nil { return err }
}
if err := cloud.DeleteServerGroup(group.ID); err != nil { return err }
Defensive patterns

Strategy: try-catch

Validate before calling

// Check group membership and ownership before deleting
members, _ := listServersInGroup(groupID)
if len(members) > 0 {
	return fmt.Errorf("server group %s still has %d members; delete instances first", groupID, len(members))
}

Try / catch

err := cloud.DeleteServerGroup(groupID)
if err != nil {
	var gerr gophercloud.ErrUnexpectedResponseCode
	if errors.As(err, &gerr) {
		switch gerr.Actual {
		case 403, 409:
			return fmt.Errorf("server group %s is busy or owned elsewhere; drain members and check permissions: %w", groupID, err)
		case 404:
			return nil // already gone
		}
	}
	if errors.Is(err, wait.ErrWaitTimeout) {
		return fmt.Errorf("server group %s deletion timed out after retries", groupID)
	}
	return err
}

Prevention

When it happens

Trigger: servergroups.Delete(...).ExtractErr() returns a non-404 error: 403 because the server group still has members or belongs to another project, 404 handled as success (not this error), 401 expired token, 409 conflict (group busy/being modified), or network failure to the compute endpoint.

Common situations: Tearing down a cluster whose server group still contains running instances the cloud forbids deleting; cross-project/role misconfiguration so the token cannot delete resources; nova-api outage during kops delete cluster; a hard 409 while another process mutates the group.

Related errors


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