kubernetes/kops · error
error deleting network %s: %v
Error message
error deleting network %s: %v
What it means
Thrown by deleteNetwork when Compute Networks().Delete fails with any error except NotFound. The cluster VPC network could not be deleted; typically because dependent resources (subnets, firewall rules, VPN, peering) still exist.
Source
Thrown at pkg/resources/gce/gce.go:1260
}
func deleteNetwork(cloud fi.Cloud, r *resources.Resource) error {
c := cloud.(gce.GCECloud)
o := r.Obj.(*compute.Network)
klog.V(2).Infof("deleting GCE network %s", o.SelfLink)
u, err := gce.ParseGoogleCloudURL(o.SelfLink)
if err != nil {
return err
}
op, err := c.Compute().Networks().Delete(u.Project, u.Name)
if err != nil {
if gce.IsNotFound(err) {
klog.Infof("Network not found, assuming deleted: %q", o.SelfLink)
return nil
}
return fmt.Errorf("error deleting network %s: %v", o.SelfLink, err)
}
return c.WaitForOp(op)
}
func (d *clusterDiscoveryGCE) matchesClusterName(name string) bool {
// Names could have hypens in them, so really there is no limit.
// 8 hyphens feels like enough for any "reasonable" name
maxParts := 8
return d.matchesClusterNameMultipart(name, maxParts)
}
// matchesClusterNameMultipart checks if the name could have been generated by our cluster
// considering all the prefixes separated by `-`. maxParts limits the number of parts we consider.
func (d *clusterDiscoveryGCE) matchesClusterNameMultipart(name string, maxParts int) bool {
tokens := strings.Split(name, "-")
View on GitHub (pinned to 4c8573c808)
Solutions
- Delete remaining dependent resources first: subnetworks, firewall rules, routes, VPN tunnels, peerings.
- Grant compute.networkAdmin so networks.delete is permitted.
- Retry `kops delete cluster` after cleanup — it is idempotent (NotFound tolerated).
- For shared VPC (XPN) networks, detach/fix the host-project attachment before deleting.
- Clean up manually with `gcloud compute networks delete NAME` if kops state no longer tracks them.
Example fix
// before
return fmt.Errorf("error deleting network %s: %v", o.SelfLink, err)
// after
if apiErr, ok := err.(*googleapi.Error); ok && apiErr.Code == 400 && strings.Contains(apiErr.Message, "in use") {
return fmt.Errorf("network %s still has dependent resources (subnets/firewall rules); delete them first: %w", o.SelfLink, err)
}
return fmt.Errorf("error deleting network %s: %w", o.SelfLink, err) Defensive patterns
Strategy: try-catch
Validate before calling
// before deleting the network, confirm no dependents remain
if subnets, _ := listSubnetsInNetwork(project, networkName); len(subnets) > 0 {
return fmt.Errorf("network %s still has %d subnets", networkName, len(subnets))
} Type guard
func isNetworkInUse(err error) bool {
ge, ok := err.(*googleapi.Error)
return ok && ge.Code == 400 && strings.Contains(ge.Message, "in use")
} Try / catch
op, err := c.Compute().Networks().Delete(u.Project, u.Name)
if err != nil {
if gce.IsNotFound(err) {
return nil
}
if isNetworkInUse(err) {
return fmt.Errorf("delete dependent subnets/firewall rules first: %w", err)
}
return fmt.Errorf("error deleting network %s: %w", o.SelfLink, err)
}
return c.WaitForOp(op) Prevention
- Always tear down subnets, firewall rules, and routes before the network.
- Detach VPC peering / shared-VPC attachments first.
- Use compute.networkAdmin role for the teardown identity.
- Re-run delete cluster after fixing partial failures; it tolerates NotFound.
When it happens
Trigger: Networks().Delete(project, name) returns 400 failedPrecondition ('network is in use' by subnetworks/firewall rules/routes), 403 permission denied, 409 concurrent operation, or transient 5xx.
Common situations: Cluster deletion order left subnets/firewall rules behind; peering or shared VPC attachments hold the network; IAM lacks networks.delete; earlier deletion steps failed leaving dependents.
Related errors
- error listing networks: %v
- failed to parse subnet CIDR %q: %w
- error deleting Subnetwork %s: %v
- error deleting router %s: %v
- error deleting ServiceAccount %s: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/c77c52a7e74aa904.
Report an issue: GitHub.