kubernetes/kops · error
could not delete port %q: %v
Error message
could not delete port %q: %v
What it means
Wrapped error returned while deleting OpenStack Neutron ports belonging to an instance group during cluster teardown. kOps enumerates the group's ports and calls DeletePort for each; if the Neutron API rejects or fails a single port deletion, the whole operation aborts with this message wrapping the port ID and underlying error.
Source
Thrown at upup/pkg/fi/cloudup/openstack/cloud.go:635
}
func deletePorts(c OpenstackCloud, instanceGroupName string, clusterName string) error {
tags := []string{
fmt.Sprintf("%s=%s", TagClusterName, clusterName),
fmt.Sprintf("%s=%s", TagKopsInstanceGroup, instanceGroupName),
}
ports, err := c.ListPorts(ports.ListOpts{Tags: strings.Join(tags, ",")})
if err != nil {
return fmt.Errorf("could not list ports %v", err)
}
for _, port := range ports {
klog.V(2).Infof("Delete port '%s' (%s)", port.Name, port.ID)
err := c.DeletePort(port.ID)
if err != nil {
return fmt.Errorf("could not delete port %q: %v", port.ID, err)
}
}
return nil
}
func deleteGroup(c OpenstackCloud, g *cloudinstances.CloudInstanceGroup) error {
cluster := g.Raw.(*kops.Cluster)
allInstances, err := c.ListInstances(servers.ListOpts{
Name: fmt.Sprintf("^%s", g.InstanceGroup.Name),
})
if err != nil {
return err
}
instances := []servers.Server{}
for _, instance := range allInstances {
if !InstanceInClusterAndIG(instance, cluster.Name, g.InstanceGroup.Name) {View on GitHub (pinned to 4c8573c808)
Solutions
- Check the wrapped %v error for the HTTP status; if 404, the port is already gone and the group cleanup can be re-run safely
- Ensure instances in the group are deleted before ports (kOps deletes instances first in deleteInstanceGroup)
- Re-run kops delete after the conflict clears; 409 errors are usually transient while resources detach
- Verify OS_* cloud credentials and Neutron endpoint reachability
Defensive patterns
Strategy: retry
Validate before calling
// before teardown
ports, _ := c.ListPorts(network.ListOpts{})
for _, p := range ports {
if attached(p.DeviceID) { klog.Infof("port %s still attached; delete instances first", p.ID) }
} Try / catch
// Go: check wrapped error and classify
if err := c.DeletePort(port.ID); err != nil {
var gErr gophercloud.ErrUnexpectedResponseCode
if errors.As(err, &gErr) && gErr.Actual == 404 { continue /* already gone */ }
return fmt.Errorf("could not delete port %q: %v", port.ID, err)
} Prevention
- Always delete instances before ports
- Re-run idempotent delete passes instead of failing hard on 404
- Keep Neutron credentials/quota valid before teardown
- Check for parallel kops runs to avoid delete races
When it happens
Trigger: DeletePort(port.ID) returns a non-nil error, typically a 404 (port already gone), 409 (port in use by an active instance/DHCP), or a network/auth failure against the Neutron endpoint.
Common situations: Port already deleted by a parallel cleanup or manual run; instance still holding the port (must delete instance first); Neutron quota or connectivity issues; stale credentials after Keystone token expiry.
Related errors
- error describing Network: %v
- network %q not found
- error building neutron client: %w
- could not establish floating network id
- error listing subnets in network %q: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/c1b5070ea6effd4f.
Report an issue: GitHub.