{"record":{"id":"78d95421055d89d9","repo":"kubernetes/kops","slug":"error-getting-forwardingrule-q-w","errorCode":null,"errorMessage":"error getting ForwardingRule %q: %w","messagePattern":"error getting ForwardingRule %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/resources/gce/gce.go","lineNumber":589,"sourceCode":"\n\t\t// find the objects if this is a Kubernetes LoadBalancer\n\t\tif strings.HasPrefix(firewallRule.Name, \"k8s-fw-\") {\n\t\t\t// We build a list of resources if this is a k8s firewall rule,\n\t\t\t// but we only add them once all the checks are complete\n\t\t\tvar k8sResources []*resources.Resource\n\n\t\t\tk8sResources = append(k8sResources, firewallRuleResource)\n\n\t\t\t// We lookup the forwarding rule by name, but we then validate that it points to one of our resources\n\t\t\tforwardingRuleName := strings.TrimPrefix(firewallRule.Name, \"k8s-fw-\")\n\t\t\tforwardingRule, err := c.Compute().ForwardingRules().Get(ctx, c.Project(), c.Region(), forwardingRuleName)\n\t\t\tif err != nil {\n\t\t\t\tif gce.IsNotFound(err) {\n\t\t\t\t\t// We looked it up by name, so an error isn't unlikely\n\t\t\t\t\tklog.Warningf(\"could not find forwarding rule %q, assuming firewallRule %q is not a k8s rule\", forwardingRuleName, firewallRule.Name)\n\t\t\t\t\tcontinue nextFirewallRule\n\t\t\t\t}\n\t\t\t\treturn nil, fmt.Errorf(\"error getting ForwardingRule %q: %w\", forwardingRuleName, err)\n\t\t\t}\n\n\t\t\tforwardingRuleResource := &resources.Resource{\n\t\t\t\tName:    forwardingRule.Name,\n\t\t\t\tID:      forwardingRule.Name,\n\t\t\t\tType:    typeForwardingRule,\n\t\t\t\tDeleter: deleteForwardingRule,\n\t\t\t\tObj:     forwardingRule,\n\t\t\t}\n\t\t\tif forwardingRule.Target != \"\" {\n\t\t\t\tforwardingRuleResource.Blocks = append(forwardingRuleResource.Blocks, typeTargetPool+\":\"+gce.LastComponent(forwardingRule.Target))\n\t\t\t}\n\t\t\tk8sResources = append(k8sResources, forwardingRuleResource)\n\n\t\t\t// TODO: Can we get k8s to set labels on the ForwardingRule?\n\n\t\t\t// TODO: Check description?  It looks like e.g. description: '{\"kubernetes.io/service-name\":\"kube-system/guestbook\"}'\n","sourceCodeStart":571,"sourceCodeEnd":607,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/resources/gce/gce.go#L571-L607","documentation":"This error wraps a failure from the Google Compute Engine API when looking up a ForwardingRule by name during cluster resource discovery in listFirewallRules. For each k8s-related firewall rule, kOps resolves the forwarding rule that targets it; if the Compute API Get call fails with anything other than a 404 (which is handled gracefully as 'not a k8s rule'), the underlying GCP error is wrapped and discovery aborts. The %w wrapping preserves the original GCE API error for errors.Is/As inspection.","triggerScenarios":"c.Compute().ForwardingRules().Get(project, region, forwardingRuleName) returns a non-NotFound error: API quota/exceeded rate limits, permission denied on compute.forwardingRules.get, transient 5xx from the Compute API, invalid region configuration, or network failure reaching the GCE endpoint.","commonSituations":"Service account missing compute.viewer role after credential rotation; GCE API quota exhaustion in a busy project; regional mismatch where the forwarding rule lives in a different region than c.Region(); transient GCP outages during cluster deletion; private DNS/proxy issues blocking googleapis.com.","solutions":["Re-run the kops command; transient 5xx/rate-limit errors usually resolve on retry (with backoff if quota-related).","Verify the service account has compute.forwardingRules.get permission (roles/compute.viewer or compute.networkAdmin on the project).","Check that the cluster's region in the cluster spec matches where the forwarding rules actually exist.","Inspect the wrapped error with errors.As to the Google API error to read the exact GCP status code (403 vs 429 vs 500).","If the region is wrong, fix spec.networking/region or point kops at the correct cluster."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// before listing, verify access\nforwardingRule, err := computeService.ForwardingRules.Get(project, region, name).Do()\nif err != nil {\n    if gce.IsNotFound(err) { return nil } // benign: not a k8s rule\n    if gerr, ok := err.(*googleapi.Error); ok {\n        if gerr.Code == 403 { return fmt.Errorf(\"missing compute.forwardingRules.get IAM: %w\", err) }\n    }\n    return err\n}","typeGuard":"func isGCEAPIError(err error) (*googleapi.Error, bool) {\n    var gerr *googleapi.Error\n    if errors.As(err, &gerr) { return gerr, true }\n    return nil, false\n}","tryCatchPattern":"resourceMap, err := listFirewallRules(ctx, c)\nif err != nil {\n    var gerr *googleapi.Error\n    if errors.As(err, &gerr) && (gerr.Code == 429 || gerr.Code >= 500) {\n        // transient: retry with backoff\n    }\n    return fmt.Errorf(\"firewall rule discovery failed: %w\", err)\n}","preventionTips":["Grant the kops service account roles/compute.networkAdmin (or compute.viewer) on the project","Keep cluster region consistent with where load balancer resources were created","Wrap long-running deletes in retry with exponential backoff for 429/5xx","Use errors.As with *googleapi.Error to branch on the GCP status code","Watch GCP quota metrics before bulk teardown operations"],"tags":["gce","gcp","load-balancer","api-error"],"backgroundTag":"gce-api-request-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"}