kubernetes/kops · error

unable to find resource for %s: %w

Error message

unable to find resource for %s: %w

What it means

pruneObjectsOfKind asks the DeferredDiscoveryRESTMapper to map a GroupKind to a REST resource. If the discovery mapper has no mapping (kind unknown to the cluster), the error is wrapped as `unable to find resource for <gk>` and pruning of that kind aborts.

Source

Thrown at channels/pkg/channels/prune.go:83

	}

	for i := range spec.Kinds {
		pruneKind := &spec.Kinds[i]
		gk := schema.GroupKind{Group: pruneKind.Group, Kind: pruneKind.Kind}
		if err := p.pruneObjectsOfKind(ctx, gk, pruneKind, objectsByKind[gk]); err != nil {
			return fmt.Errorf("failed to prune objects of kind %s: %w", gk, err)
		}
	}

	return nil
}

func (p *Pruner) pruneObjectsOfKind(ctx context.Context, gk schema.GroupKind, spec *api.PruneKindSpec, keepObjects []*kubemanifest.Object) error {
	klog.Infof("pruning objects of kind: %v", gk)

	restMapping, err := p.RESTMapper.RESTMapping(gk)
	if err != nil {
		return fmt.Errorf("unable to find resource for %s: %w", gk, err)
	}

	gvr := restMapping.Resource

	var listOptions v1.ListOptions
	listOptions.LabelSelector = spec.LabelSelector
	listOptions.FieldSelector = spec.FieldSelector

	baseResource := p.Client.Resource(gvr)
	if len(spec.Namespaces) == 0 {
		objects, err := baseResource.List(ctx, listOptions)
		if err != nil {
			return fmt.Errorf("error listing objects: %w", err)
		}
		if err := p.pruneObjects(ctx, gvr, objects, keepObjects); err != nil {
			return err
		}
	} else {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Check the kind exists: `kubectl api-resources | grep <kind>` and align the PruneSpec with actual group/kind
  2. Install the CRD before running the channel update/prune
  3. Reset the discovery cache (restart the controller/kops process) if a CRD was just installed
  4. Remove obsolete kinds from the PruneSpec for clusters where the API no longer exists

Example fix

// before
kinds:
- group: monitoring.coreos.com
  kind: ServiceMonitor  # CRD not installed yet
// after
// apply the CRD first, or:
kinds:
- group: apps
  kind: Deployment
Defensive patterns

Strategy: validation

Validate before calling

gk := schema.GroupKind{Group: "monitoring.coreos.com", Kind: "ServiceMonitor"}
if _, err := restMapper.RESTMapping(gk); err != nil {
    return fmt.Errorf("skip prune, kind %v unavailable in cluster", gk)
}

Try / catch

if err := pruner.Prune(ctx, manifest, spec); err != nil {
    if strings.Contains(err.Error(), "unable to find resource for") {
        klog.Warningf("prune kind unknown to cluster, skipping: %v", err)
        return nil // or install the CRD and retry
    }
    return err
}

Prevention

When it happens

Trigger: The PruneSpec lists a kind whose resource does not exist on the API server: wrong group/kind, CRD not installed, API removed in the cluster's Kubernetes version, or discovery cache is stale.

Common situations: Typo'd kind in prune spec; pruning a custom resource before its CRD is applied; cluster upgraded to a version that removed an API (e.g. policy/v1beta1 kinds); discovery cache stale after CRD install.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/213249d4beea3efc. Report an issue: GitHub.