{"record":{"id":"659bbd8880c7cc67","repo":"kubernetes/kops","slug":"failed-to-prune-objects-of-kind-s-w","errorCode":null,"errorMessage":"failed to prune objects of kind %s: %w","messagePattern":"failed to prune objects of kind (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"channels/pkg/channels/prune.go","lineNumber":71,"sourceCode":"\t\tgv, err := schema.ParseGroupVersion(object.APIVersion())\n\t\tif err != nil || gv.Version == \"\" {\n\t\t\treturn fmt.Errorf(\"failed to parse apiVersion %q\", object.APIVersion())\n\t\t}\n\t\tkind := object.Kind()\n\t\tif kind == \"\" {\n\t\t\treturn fmt.Errorf(\"failed to find kind in object\")\n\t\t}\n\n\t\tgvk := gv.WithKind(kind)\n\t\tgk := gvk.GroupKind()\n\t\tobjectsByKind[gk] = append(objectsByKind[gk], object)\n\t}\n\n\tfor i := range spec.Kinds {\n\t\tpruneKind := &spec.Kinds[i]\n\t\tgk := schema.GroupKind{Group: pruneKind.Group, Kind: pruneKind.Kind}\n\t\tif err := p.pruneObjectsOfKind(ctx, gk, pruneKind, objectsByKind[gk]); err != nil {\n\t\t\treturn fmt.Errorf(\"failed to prune objects of kind %s: %w\", gk, err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (p *Pruner) pruneObjectsOfKind(ctx context.Context, gk schema.GroupKind, spec *api.PruneKindSpec, keepObjects []*kubemanifest.Object) error {\n\tklog.Infof(\"pruning objects of kind: %v\", gk)\n\n\trestMapping, err := p.RESTMapper.RESTMapping(gk)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to find resource for %s: %w\", gk, err)\n\t}\n\n\tgvr := restMapping.Resource\n\n\tvar listOptions v1.ListOptions\n\tlistOptions.LabelSelector = spec.LabelSelector","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/channels/pkg/channels/prune.go#L53-L89","documentation":"Prune iterates the PruneSpec.Kinds list and delegates to pruneObjectsOfKind for each GroupKind. Any failure inside (mapping, listing, deleting) is wrapped as `failed to prune objects of kind <gk>`, preserving the full chain (%w) so the root cause is inspectable with errors.As/Is.","triggerScenarios":"Any pruneKind entry in the PruneSpec fails processing: RESTMapper cannot map the kind, list calls fail (cluster/RBAC/selector issues), or deletion of a stale object fails.","commonSituations":"Prune spec referencing a kind not present in the cluster (typo or removed API); RBAC denying list/delete on the group; API server errors mid-prune; network partition during prune.","solutions":["Unwrap the chain (errors.Unwrap / %v of inner error) to see whether mapping, listing, or deleting failed","Fix the specific inner cause (see errors 56–59 for each sub-case)","Correct the Group/Kind spelling in the channels PruneSpec","Verify RBAC allows list and delete for the kind being pruned"],"exampleFix":"// before\nkinds:\n- group: apps\n  kind: Deploymnets   # typo\n// after\nkinds:\n- group: apps\n  kind: Deployment","handlingStrategy":"try-catch","validationCode":"// verify every prune kind is mappable before pruning\nfor _, k := range spec.Kinds {\n    gk := schema.GroupKind{Group: k.Group, Kind: k.Kind}\n    if _, err := restMapper.RESTMapping(gk); err != nil {\n        return fmt.Errorf(\"prune kind %v not present in cluster: %w\", gk, err)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := pruner.Prune(ctx, manifest, spec); err != nil {\n    var gkErr *fmt.WrapError // inspect chain\n    klog.Errorf(\"prune failed: %v\", err) // %w chain shows the inner mapping/list/delete cause\n    return err\n}","preventionTips":["Keep PruneSpec kinds aligned with kinds actually in the addon manifest","Install CRDs before running channel updates that prune custom resources","Test prune specs against `kubectl api-resources` output for the target cluster version"],"tags":["prune","kubernetes","addon","cleanup"],"backgroundTag":"prune-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"}