kubernetes/kops · error
error deleting FirewallRule %s: %v
Error message
error deleting FirewallRule %s: %v
What it means
Wraps a failure from Compute Firewalls().Delete in deleteFirewallRule during cluster teardown. NotFound is handled as already-deleted success, so this surfaces genuine delete failures: permission denied, rate limits, server errors, or firewall rules locked by other GCP features. Message includes the firewall rule's SelfLink and the raw error.
Source
Thrown at pkg/resources/gce/gce.go:723
// deleteFirewallRule is the helper function to delete a Resource for a Firewall object
func deleteFirewallRule(cloud fi.Cloud, r *resources.Resource) error {
c := cloud.(gce.GCECloud)
t := r.Obj.(*compute.Firewall)
klog.V(2).Infof("Deleting GCE FirewallRule %s", t.SelfLink)
u, err := gce.ParseGoogleCloudURL(t.SelfLink)
if err != nil {
return err
}
op, err := c.Compute().Firewalls().Delete(u.Project, u.Name)
if err != nil {
if gce.IsNotFound(err) {
klog.Infof("FirewallRule not found, assuming deleted: %q", t.SelfLink)
return nil
}
return fmt.Errorf("error deleting FirewallRule %s: %v", t.SelfLink, err)
}
return c.WaitForOp(op)
}
func (d *clusterDiscoveryGCE) listRoutes(ctx context.Context, resourceMap map[string]*resources.Resource) ([]*resources.Resource, error) {
c := d.gceCloud
var resourceTrackers []*resources.Resource
instancesToDelete := make(map[string]*resources.Resource)
migsToDelete := make(map[string]*resources.Resource)
for _, resource := range resourceMap {
switch resource.Type {
case typeInstance:
instancesToDelete[resource.ID] = resource
case typeInstanceGroupManager:
migsToDelete[resource.ID] = resourceView on GitHub (pinned to 4c8573c808)
Solutions
- Check IAM for compute.firewalls.delete on the project (or host project in shared VPC).
- If the rule is owned by GKE/another controller, delete it via that system or in the console rather than kops.
- Retry the delete; 429/5xx failures are typically transient.
- Confirm the rule is not recreated by an active controller; remove the source of recreation first.
- If already deleted, re-run — NotFound is treated as success.
Defensive patterns
Strategy: retry
Validate before calling
// confirm the firewall rule still exists and is kOps-owned before delete
fw, err := computeService.Firewalls.Get(project, ruleName).Do()
if err != nil { /* 404 means already gone */ }
if fw != nil && !strings.Contains(fw.Description, clusterTag) {
return fmt.Errorf("firewall %s not owned by this cluster", ruleName)
} Type guard
func isGCEAPIError(err error) (*googleapi.Error, bool) {
var gerr *googleapi.Error
return gerr, errors.As(err, &gerr)
} Try / catch
err := deleteFirewallRule(t)
var gerr *googleapi.Error
if err != nil {
if errors.As(err, &gerr) && gerr.Code == 404 { return nil } // fine
if errors.As(err, &gerr) && (gerr.Code == 429 || gerr.Code >= 500) {
// retry with backoff
}
return err
} Prevention
- Grant compute.firewalls.delete on the project (and host project for shared VPC)
- Disable GKE/controllers that recreate firewall rules before kops teardown
- Serialize cluster deletion — no concurrent kops runs on the same cluster
- Retry 429/5xx with exponential backoff
- Remember NotFound is treated as success; just re-run after transient failures
When it happens
Trigger: c.Compute().Firewalls().Delete(u.Project, u.Name) returns 403 (missing compute.firewalls.delete), 429 quota, 5xx, or a conflict because the rule is managed/locked by another system (e.g. GKE control plane, shared VPC host project policies).
Common situations: Shared VPC setups where the kops service account lacks firewall permissions on the host project; firewall rules recreated by GKE or another controller racing the delete; expired/rotated credentials mid-teardown; transient GCP outages.
Related errors
- error deleting HTTP HealthCheck %s: %v
- error deleting Route %s: %v
- error deleting Address %s: %v
- getting FirewallRule %q: %w
- either SourceRanges or SourceTags should be specified when D
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/291f85fd8a0c07fd.
Report an issue: GitHub.