{"record":{"id":"8b9b8c0d950b1f65","repo":"kubernetes/kops","slug":"deleting-forwardingrule-s-w","errorCode":null,"errorMessage":"deleting forwardingRule %s: %w","messagePattern":"deleting forwardingRule (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/gcetasks/forwardingrule.go","lineNumber":404,"sourceCode":"\n// Item returns the forwarding rule name\nfunc (d *deleteForwardingRule) Item() string {\n\treturn d.forwardingRule.Name\n}\n\nfunc (d *deleteForwardingRule) Delete(t fi.CloudupTarget) error {\n\tctx := context.TODO()\n\n\tgceTarget, ok := t.(*gce.GCEAPITarget)\n\tif !ok {\n\t\treturn fmt.Errorf(\"unexpected target type for deletion: %T\", t)\n\t}\n\n\tcloud := gceTarget.Cloud\n\tname := d.forwardingRule.Name\n\n\tif _, err := cloud.Compute().ForwardingRules().Delete(ctx, cloud.Project(), cloud.Region(), name); err != nil {\n\t\treturn fmt.Errorf(\"deleting forwardingRule %s: %w\", name, err)\n\t}\n\n\treturn nil\n}\n\n// String returns a string representation of the task\nfunc (d *deleteForwardingRule) String() string {\n\treturn d.TaskName() + \"-\" + d.Item()\n}\n\nfunc (d *deleteForwardingRule) DeferDeletion() bool {\n\t// We want to defer deletion, in case new nodes are launched with\n\t// the old configuration during the rolling-update operation.\n\treturn true\n}\n","sourceCodeStart":386,"sourceCodeEnd":420,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/gcetasks/forwardingrule.go#L386-L420","documentation":"This wraps the error returned by the GCE Compute API call ForwardingRules().Delete(ctx, project, region, name) during deletion of a regional forwarding rule. The %w wrapping preserves the underlying googleapi error (404, 4xx/5xx, quota, permission) for errors.Is/As inspection.","triggerScenarios":"cloud.Compute().ForwardingRules().Delete fails for the named regional forwarding rule — network error, expired/insufficient credentials, missing compute.forwardingRules.delete permission, rate limiting, or the rule being in a state that forbids deletion.","commonSituations":"Service account lacks compute.forwardingRules.delete IAM permission; GCE API transient 500/503; forwarding rule still attached to a target pool/proxy during teardown; regional mismatch between the task and the actual rule location.","solutions":["Read the wrapped googleapi error (errors.As to *googleapi.Error) and act on its code (403 => IAM, 429 => retry, 404 => already gone)","Verify the service account has compute.forwardingRules.delete (e.g. roles/compute.networkAdmin)","Retry after backoff for transient 5xx/429; re-run kops delete/apply since deletion is idempotent","Ensure the rule's region matches cloud.Region() used by the cluster"],"exampleFix":"null","handlingStrategy":"try-catch","validationCode":"// pre-check IAM and resource existence before delete\n_, err := cloud.Compute().ForwardingRules().Get(ctx, cloud.Project(), cloud.Region(), name)\nif gce.IsNotFound(err) { return nil } // nothing to delete","typeGuard":null,"tryCatchPattern":"var gerr *googleapi.Error\nif errors.As(err, &gerr) {\n\tswitch gerr.Code {\n\tcase 404: // already deleted, ignore\n\tcase 403: // fix IAM: compute.forwardingRules.delete\n\tcase 429, 500, 503: // retry with backoff\n\t}\n}","preventionTips":["Grant the service account roles/compute.networkAdmin or equivalent delete permissions","Treat 404 as success — deletes are idempotent","Retry transient 429/5xx with exponential backoff","Verify region matches the cluster's cloud.Region()"],"tags":["gce","forwarding-rule","cloud-api","deletion"],"backgroundTag":"gce-api-delete-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}