kubernetes/kops · error
unknown scope for gvk %s: %q
Error message
unknown scope for gvk %s: %q
What it means
A fallback branch in dynamicResource: after namespace-scoped and root-scoped cases, any unrecognized RESTScopeName indicates the RESTMapper returned data the client does not understand. The code itself calls this panic-level, i.e. it should be unreachable with a correct discovery client and k8s.io/client-go version.
Source
Thrown at pkg/applylib/applyset/unstructuredclient.go:75
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
default:
// Internal error ... this is panic-level
return nil, fmt.Errorf("unknown scope for gvk %s: %q", gvk, restMapping.Scope.Name())
}
}
// Patch performs a Patch operation, used for server-side apply and client-side patch.
func (c *UnstructuredClient) Patch(ctx context.Context, gvk schema.GroupVersionKind, nn types.NamespacedName, patchType types.PatchType, data []byte, opt metav1.PatchOptions) (*unstructured.Unstructured, error) {
dynamicResource, err := c.dynamicResource(ctx, gvk, nn.Namespace)
if err != nil {
return nil, err
}
name := nn.Name
patched, err := dynamicResource.Patch(ctx, name, patchType, data, opt)
if err != nil {
return nil, fmt.Errorf("error patching object: %w", err)
}
return patched, nil
}
View on GitHub (pinned to 4c8573c808)
Solutions
- Check go.mod for mismatched k8s.io/client-go and apimachinery versions and run make gomod to realign vendoring
- Re-run discovery / rebuild the RESTMapper cache and retry
- If using a custom RESTMapper (e.g. in tests), ensure its mappings return meta.RESTScopeNamespace or meta.RESTScopeRoot
- Report upstream with the gvk and scope string if it reproduces with stock client-go
Defensive patterns
Strategy: try-catch
Validate before calling
mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version)
if err == nil {
scope := mapping.Scope.Name()
if scope != meta.RESTScopeNameNamespace && scope != meta.RESTScopeNameRoot {
return fmt.Errorf("unexpected REST scope %q for %s; check client-go versions", scope, gvk)
}
} Type guard
func knownScope(mapping *meta.RESTMapping) bool {
name := mapping.Scope.Name()
return name == meta.RESTScopeNameNamespace || name == meta.RESTScopeNameRoot
} Try / catch
res, err := client.Get(ctx, gvk, nn)
if err != nil {
if strings.HasPrefix(err.Error(), "unknown scope for gvk") {
// dependency/invariant bug: rebuild discovery cache, realign client-go
return fmt.Errorf("internal: bad REST mapping for %s: %w", gvk, err)
}
return err
} Prevention
- Keep k8s.io/client-go and apimachinery versions aligned in go.mod (make gomod)
- Rebuild the RESTMapper after discovery errors instead of reusing stale mappings
- Avoid custom RESTMappers in production paths
- Treat this error as a bug report trigger, not a user-facing condition
When it happens
Trigger: Only reachable if restMapping.Scope.Name() returns a value other than "namespace" or "" (root), which implies a corrupted/mis-built RESTMapping or an unexpected client-go version change.
Common situations: Practically never hit in production; may appear when vendoring mismatched versions of k8s.io/client-go / discovery, or with custom/simulated RESTMappers in tests returning fake scopes.
Related errors
- unable to find resource for %s: %w
- error querying kubernetes version: %v
- cannot parse kubernetes version %q
- error getting rest mapping for %v: %w
- listing server preferred resources: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/ffb2449036be6511.
Report an issue: GitHub.