{"record":{"id":"c77c52a7e74aa904","repo":"kubernetes/kops","slug":"error-deleting-network-s-v","errorCode":null,"errorMessage":"error deleting network %s: %v","messagePattern":"error deleting network (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/resources/gce/gce.go","lineNumber":1260,"sourceCode":"}\n\nfunc deleteNetwork(cloud fi.Cloud, r *resources.Resource) error {\n\tc := cloud.(gce.GCECloud)\n\to := r.Obj.(*compute.Network)\n\n\tklog.V(2).Infof(\"deleting GCE network %s\", o.SelfLink)\n\tu, err := gce.ParseGoogleCloudURL(o.SelfLink)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\top, err := c.Compute().Networks().Delete(u.Project, u.Name)\n\tif err != nil {\n\t\tif gce.IsNotFound(err) {\n\t\t\tklog.Infof(\"Network not found, assuming deleted: %q\", o.SelfLink)\n\t\t\treturn nil\n\t\t}\n\t\treturn fmt.Errorf(\"error deleting network %s: %v\", o.SelfLink, err)\n\t}\n\n\treturn c.WaitForOp(op)\n}\n\nfunc (d *clusterDiscoveryGCE) matchesClusterName(name string) bool {\n\t// Names could have hypens in them, so really there is no limit.\n\t// 8 hyphens feels like enough for any \"reasonable\" name\n\tmaxParts := 8\n\n\treturn d.matchesClusterNameMultipart(name, maxParts)\n}\n\n// matchesClusterNameMultipart checks if the name could have been generated by our cluster\n// considering all the prefixes separated by `-`.  maxParts limits the number of parts we consider.\nfunc (d *clusterDiscoveryGCE) matchesClusterNameMultipart(name string, maxParts int) bool {\n\ttokens := strings.Split(name, \"-\")\n","sourceCodeStart":1242,"sourceCodeEnd":1278,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/resources/gce/gce.go#L1242-L1278","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nreturn fmt.Errorf(\"error deleting network %s: %v\", o.SelfLink, err)\n// after\nif apiErr, ok := err.(*googleapi.Error); ok && apiErr.Code == 400 && strings.Contains(apiErr.Message, \"in use\") {\n\treturn fmt.Errorf(\"network %s still has dependent resources (subnets/firewall rules); delete them first: %w\", o.SelfLink, err)\n}\nreturn fmt.Errorf(\"error deleting network %s: %w\", o.SelfLink, err)","handlingStrategy":"try-catch","validationCode":"// before deleting the network, confirm no dependents remain\nif subnets, _ := listSubnetsInNetwork(project, networkName); len(subnets) > 0 {\n\treturn fmt.Errorf(\"network %s still has %d subnets\", networkName, len(subnets))\n}","typeGuard":"func isNetworkInUse(err error) bool {\n\tge, ok := err.(*googleapi.Error)\n\treturn ok && ge.Code == 400 && strings.Contains(ge.Message, \"in use\")\n}","tryCatchPattern":"op, err := c.Compute().Networks().Delete(u.Project, u.Name)\nif err != nil {\n\tif gce.IsNotFound(err) {\n\t\treturn nil\n\t}\n\tif isNetworkInUse(err) {\n\t\treturn fmt.Errorf(\"delete dependent subnets/firewall rules first: %w\", err)\n\t}\n\treturn fmt.Errorf(\"error deleting network %s: %w\", o.SelfLink, err)\n}\nreturn c.WaitForOp(op)","preventionTips":["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."],"tags":["gce","network","vpc","deletion"],"backgroundTag":"gce-resource-delete-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}