{"record":{"id":"4f0d4b42d508b094","repo":"kubernetes/kops","slug":"unexpected-target-type-for-deletion-t-4f0d4b","errorCode":null,"errorMessage":"unexpected target type for deletion: %T","messagePattern":"unexpected target type for deletion: %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/gcetasks/forwardingrule.go","lineNumber":397,"sourceCode":"\nvar _ fi.CloudupDeletion = (*deleteForwardingRule)(nil)\n\n// TaskName returns the task name\nfunc (d *deleteForwardingRule) TaskName() string {\n\treturn \"ForwardingRule\"\n}\n\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 {","sourceCodeStart":379,"sourceCodeEnd":415,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/gcetasks/forwardingrule.go#L379-L415","documentation":"deleteForwardingRule.Delete is invoked by the fi executor with a target it was configured with. It asserts that the target is a *gce.GCEAPITarget (the only target that can talk to the GCE Compute API) and returns this error for any other target type (e.g. a dry-run/terraform target). It is an internal invariant check, not a cloud API failure.","triggerScenarios":"The fi framework runs Delete against a CloudupTarget that is not *gce.GCEAPITarget — typically when the executor is running with a target like TargetTerraform/TargetDryRun that reaches a delete path, or a target from a different cloud provider is passed due to executor misconfiguration.","commonSituations":"Running kops with --target=terraform or --target=dry-run while the model still resolves a deletion of a GCE forwarding rule; mixing targets when programmatically driving fi.Apply; tests passing a mock target of the wrong concrete type.","solutions":["Run apply with the real GCE API target (omit --target or use --target=direct) so deletes execute against a *gce.GCEAPITarget","Check how the fi.Target is constructed for your apply/run and ensure the GCE cloud target is passed for GCE clusters","If using a dry-run/terraform target, ensure the task's delete path is not invoked (or update the task to support that target type)"],"exampleFix":"// before (programmatic use, wrong target)\ntarget := fi.NewDryRunTarget(cloud, os.Stdout)\ncontext.Target = target\n// after\ncontext.Target = gce.NewGCEAPITarget(cloud)","handlingStrategy":"type-guard","validationCode":"// verify the target before running deletes for GCE tasks\nif _, ok := target.(*gce.GCEAPITarget); !ok {\n\treturn fmt.Errorf(\"GCE deletion requires GCEAPITarget, got %T\", target)\n}","typeGuard":"func asGCEAPITarget(t fi.CloudupTarget) (*gce.GCEAPITarget, bool) {\n\ttgt, ok := t.(*gce.GCEAPITarget)\n\treturn tgt, ok\n}","tryCatchPattern":"if err := task.Delete(target); err != nil {\n\tif strings.Contains(err.Error(), \"unexpected target type\") {\n\t\t// wrong executor target; switch to the GCE API target and retry\n\t}\n}","preventionTips":["Only run delete paths with --target=direct (real API) for GCE clusters","In programmatic fi usage, always construct the target from the cluster's cloud provider","Add a unit test asserting Delete is only reached with GCEAPITarget"],"tags":["gce","deletion","target-type","internal-invariant"],"backgroundTag":"unexpected-target-type","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"}