kubernetes/kops · error

error getting rest mapping for %v: %w

Error message

error getting rest mapping for %v: %w

What it means

UnstructuredClient.dynamicResource resolves a GroupVersionKind to a concrete resource via the RESTMapper before performing Patch/Update/Get. If the RESTMapper cannot find a mapping (resource not registered on the server, wrong GVK, or discovery failure), the error is wrapped as "error getting rest mapping for %v" including the GVK.

Source

Thrown at pkg/applylib/applyset/unstructuredclient.go:54

	// restMapper is used to map object kind to resources, and to know if objects are cluster-scoped.
	restMapper meta.RESTMapper
}

// NewUnstructuredClient constructs an UnstructuredClient
func NewUnstructuredClient(options Options) *UnstructuredClient {
	return &UnstructuredClient{
		client:     options.Client,
		restMapper: options.RESTMapper,
	}
}

// dynamicResource is a helper to get the resource for a gvk (with the namespace)
// It returns an error if a namespace is provided for a cluster-scoped resource,
// or no namespace is provided for a namespace-scoped resource.
func (c *UnstructuredClient) dynamicResource(ctx context.Context, gvk schema.GroupVersionKind, ns string) (dynamic.ResourceInterface, error) {
	restMapping, err := c.restMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
	if err != nil {
		return nil, fmt.Errorf("error getting rest mapping for %v: %w", gvk, err)
	}
	gvr := restMapping.Resource

	switch restMapping.Scope.Name() {
	case meta.RESTScopeNameNamespace:
		if ns == "" {
			// TODO: Differentiate between server-fixable vs client-fixable errors?
			return nil, fmt.Errorf("namespace was not provided for namespace-scoped object %v", gvk)
		}
		return c.client.Resource(gvr).Namespace(ns), nil

	case meta.RESTScopeNameRoot:
		if ns != "" {
			// TODO: Differentiate between server-fixable vs client-fixable errors?
			return nil, fmt.Errorf("namespace %q was provided for cluster-scoped object %v", ns, gvk)
		}
		return c.client.Resource(gvr), nil

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Confirm the resource exists: `kubectl api-resources | grep <kind>` and check the exact group/version.
  2. Apply CRDs before the custom resources that use them (order the applyset, or run twice).
  3. Fix the apiVersion/kind in the manifest to match a registered GVK.
  4. Reset/refresh the discovery RESTMapper (recreate the client) after installing new CRDs to clear stale caches.

Example fix

// before
apiVersion: apps/v1beta2
kind: Deployment
// after
apiVersion: apps/v1
kind: Deployment
Defensive patterns

Strategy: validation

Validate before calling

if _, err := restMapper.RESTMapping(gvk.GroupKind(), gvk.Version); err != nil {
    return fmt.Errorf("resource %s not present on cluster: %w", gvk, err)
}

Try / catch

if err := client.Patch(ctx, gvk, nn, types.ApplyPatchType, data, opts); err != nil {
    var discoveryErr *meta.NoKindMatchError
    if errors.As(err, &discoveryErr) {
        return applyCRDsFirst(ctx) // install CRDs, then retry
    }
    return err
}

Prevention

When it happens

Trigger: Calling Patch/Update/Get with a GVK that has no registered REST mapping: the CRD doesn't exist yet, the apiVersion/kind in the manifest is misspelled, or the discovery cache is stale after a new CRD was installed.

Common situations: Applying a custom resource before its CRD in the same apply pass; typos like apps/v1 Deployment vs extensions/v1beta1; the API server's discovery endpoints unreachable so the mapper has no data; new CRD created moments ago and the cached mapper not invalidated.

Related errors


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