kubernetes/kops · error
namespace %q was provided for cluster-scoped object %v
Error message
namespace %q was provided for cluster-scoped object %v
What it means
The mirror image of the missing-namespace check: when the RESTMapper reports the GVK as cluster-scoped (root scope, e.g. ClusterRole, Namespace, CRD), passing a namespace is contradictory and the client refuses to build a namespaced dynamic client. This prevents silently applying a namespace filter that the API server would reject.
Source
Thrown at pkg/applylib/applyset/unstructuredclient.go:69
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
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)View on GitHub (pinned to 4c8573c808)
Solutions
- Leave nn.Namespace empty ("") for cluster-scoped kinds
- Detect scope via the RESTMapper (or a known-kind list) before building NamespacedName and clear the namespace for root-scoped objects
- Audit defaulting code that blindly assigns a namespace to every object in an apply set
Example fix
// before
nn := types.NamespacedName{Name: "cluster-admin", Namespace: "default"}
// ClusterRole is cluster-scoped
client.Get(ctx, clusterRoleGVK, nn)
// after
nn := types.NamespacedName{Name: "cluster-admin"}
client.Get(ctx, clusterRoleGVK, nn) Defensive patterns
Strategy: validation
Validate before calling
clusterScopedKinds := map[string]bool{"Namespace": true, "Node": true, "ClusterRole": true, "CustomResourceDefinition": true, "PersistentVolume": true}
if clusterScopedKinds[gvk.Kind] && nn.Namespace != "" {
return fmt.Errorf("kind %s is cluster-scoped; clear nn.Namespace", gvk.Kind)
} Type guard
func isClusterScopedCall(gvk schema.GroupVersionKind, nn types.NamespacedName) bool {
return nn.Namespace != "" && clusterScopedKinds[gvk.Kind]
} Try / catch
obj, err := client.Get(ctx, gvk, nn)
if err != nil {
if strings.Contains(err.Error(), "was provided for cluster-scoped object") {
return client.Get(ctx, gvk, types.NamespacedName{Name: nn.Name})
}
return err
} Prevention
- Never blanket-default namespaces across a whole apply set; resolve scope per kind
- Keep a known cluster-scoped kind list or query the RESTMapper
- When copying namespaces from parent context, exclude root-scoped objects
- Review generated manifests for stray namespace fields on cluster-scoped kinds
When it happens
Trigger: Calling Patch, Update, or Get with a cluster-scoped gvk while nn.Namespace is non-empty, e.g. getting a Namespace or ClusterRole with Namespace set to "default".
Common situations: Generic apply logic that always fills in a default namespace for every object; copying a namespace from a parent context onto all objects; YAML lists where cluster-scoped add-ons inherit a namespace from surrounding code.
Related errors
- error querying namespace %q: %v
- error listing objects in namespace %s: %w
- namespace was not provided for namespace-scoped object %v
- error adding needs-update label: %v
- error applying annotation to record addon installation: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/984d820190b2ccec.
Report an issue: GitHub.