kubernetes/kops · error
error deleting Route %s: %v
Error message
error deleting Route %s: %v
What it means
Wraps a failure from Compute Routes().Delete in deleteRoute during cluster teardown. NotFound is treated as already-deleted success; other failures — most notably 412 conflict when the route is still assigned to an instance (kOps routes are per-instance and held by VM network interfaces) — surface here with the route SelfLink and raw error.
Source
Thrown at pkg/resources/gce/gce.go:821
}
func deleteRoute(cloud fi.Cloud, r *resources.Resource) error {
c := cloud.(gce.GCECloud)
t := r.Obj.(*compute.Route)
klog.V(2).Infof("Deleting GCE Route %s", t.SelfLink)
u, err := gce.ParseGoogleCloudURL(t.SelfLink)
if err != nil {
return err
}
op, err := c.Compute().Routes().Delete(u.Project, u.Name)
if err != nil {
if gce.IsNotFound(err) {
klog.Infof("Route not found, assuming deleted: %q", t.SelfLink)
return nil
}
return fmt.Errorf("error deleting Route %s: %v", t.SelfLink, err)
}
return c.WaitForOp(op)
}
func (d *clusterDiscoveryGCE) listAddresses() ([]*resources.Resource, error) {
c := d.gceCloud
var resourceTrackers []*resources.Resource
ctx := context.Background()
addrs, err := c.Compute().Addresses().List(ctx, c.Project(), c.Region())
if err != nil {
return nil, fmt.Errorf("error listing Addresses: %v", err)
}
for _, a := range addrs {View on GitHub (pinned to 4c8573c808)
Solutions
- Ensure instances/instance groups are deleted before routes — re-run teardown so VMs are removed first, freeing the routes.
- Wait for the holding VM to be deleted, then retry kops delete cluster (deletes are resumable).
- Check compute.routes.delete IAM permission, especially on shared VPC host projects.
- If the VM is already gone in the console but GCP still holds the route, wait a few minutes for propagation and retry.
- Force-delete orphaned VMs in the console, then re-run.
Defensive patterns
Strategy: retry
Validate before calling
// check whether any instance still uses this route (412 prevention)
route, err := computeService.Routes.Get(project, routeName).Do()
if err == nil && route.NextHopInstance != "" {
inst := lastComponent(route.NextHopInstance)
if _, err := computeService.Instances.Get(project, zone, inst).Do(); err == nil {
return fmt.Errorf("instance %s still holds route %s; delete instances first", inst, routeName)
}
} Type guard
func isGCEAPIError(err error) (*googleapi.Error, bool) {
var gerr *googleapi.Error
return gerr, errors.As(err, &gerr)
} Try / catch
err := deleteRoute(t)
var gerr *googleapi.Error
if err != nil {
if errors.As(err, &gerr) && gerr.Code == 404 { return nil }
if errors.As(err, &gerr) && (gerr.Code == 412 || gerr.Code == 429 || gerr.Code >= 500) {
// wait for VMs to drain / backoff, then retry
}
return err
} Prevention
- Delete instances/instance group managers before routes — kOps teardown ordering handles this if uninterupted
- Re-run kops delete cluster after partial failures; teardown is resumable and 404 = success
- Verify compute.routes.delete IAM, especially on shared VPC host projects
- Confirm VMs are actually gone in the console before assuming a 412 is permanent
- Avoid concurrent teardown runs racing on the same routes
When it happens
Trigger: c.Compute().Routes().Delete(u.Project, u.Name) returns 412 'route is being used by an instance', 403 permission denied, 429 rate limit, or 5xx. The 412 in-use case is characteristic: kOps routes stay in use while the instance still exists.
Common situations: Deleting a cluster while instances are still running (route held by the VM's NIC); instance group manager deletion failed earlier leaving VMs behind; shared VPC permission gaps; concurrent teardown runs.
Related errors
- error deleting HTTP HealthCheck %s: %v
- error deleting FirewallRule %s: %v
- error deleting Address %s: %v
- error listing Routes: %w
- creating gce IPAM controller: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/a197b57850d07398.
Report an issue: GitHub.