{"record":{"id":"4e93e365705d0bb4","repo":"kubernetes/kops","slug":"namespace-was-not-provided-for-namespace-scoped-ob","errorCode":null,"errorMessage":"namespace was not provided for namespace-scoped object %v","messagePattern":"namespace was not provided for namespace-scoped object (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/applylib/applyset/unstructuredclient.go","lineNumber":62,"sourceCode":"\t\trestMapper: options.RESTMapper,\n\t}\n}\n\n// dynamicResource is a helper to get the resource for a gvk (with the namespace)\n// It returns an error if a namespace is provided for a cluster-scoped resource,\n// or no namespace is provided for a namespace-scoped resource.\nfunc (c *UnstructuredClient) dynamicResource(ctx context.Context, gvk schema.GroupVersionKind, ns string) (dynamic.ResourceInterface, error) {\n\trestMapping, err := c.restMapper.RESTMapping(gvk.GroupKind(), gvk.Version)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting rest mapping for %v: %w\", gvk, err)\n\t}\n\tgvr := restMapping.Resource\n\n\tswitch restMapping.Scope.Name() {\n\tcase meta.RESTScopeNameNamespace:\n\t\tif ns == \"\" {\n\t\t\t// TODO: Differentiate between server-fixable vs client-fixable errors?\n\t\t\treturn nil, fmt.Errorf(\"namespace was not provided for namespace-scoped object %v\", gvk)\n\t\t}\n\t\treturn c.client.Resource(gvr).Namespace(ns), nil\n\n\tcase meta.RESTScopeNameRoot:\n\t\tif ns != \"\" {\n\t\t\t// TODO: Differentiate between server-fixable vs client-fixable errors?\n\t\t\treturn nil, fmt.Errorf(\"namespace %q was provided for cluster-scoped object %v\", ns, gvk)\n\t\t}\n\t\treturn c.client.Resource(gvr), nil\n\n\tdefault:\n\t\t// Internal error ... this is panic-level\n\t\treturn nil, fmt.Errorf(\"unknown scope for gvk %s: %q\", gvk, restMapping.Scope.Name())\n\t}\n}\n\n// Patch performs a Patch operation, used for server-side apply and client-side patch.\nfunc (c *UnstructuredClient) Patch(ctx context.Context, gvk schema.GroupVersionKind, nn types.NamespacedName, patchType types.PatchType, data []byte, opt metav1.PatchOptions) (*unstructured.Unstructured, error) {","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/applylib/applyset/unstructuredclient.go#L44-L80","documentation":"This error comes from the dynamicResource helper in kOps' applyset UnstructuredClient. Before creating a dynamic (unstructured) resource client, it resolves the GVK's REST scope via a discovery RESTMapper. If the object's kind is namespace-scoped but no namespace was supplied in the NamespacedName, it cannot build a valid client and returns this error instead of a confusing server-side 404/400.","triggerScenarios":"Calling Patch, Update, or Get on the UnstructuredClient with a gvk that the RESTMapper maps to RESTScopeNameNamespace while passing types.NamespacedName with an empty Namespace field.","commonSituations":"Building or passing objects like Deployment, Service, or Secret without setting metadata.namespace (e.g. parsed from YAML that omits the namespace field); constructing NamespacedName from an object before defaulting; apply-set tooling reading objects from manifests with no namespace.","solutions":["Set nn.Namespace to the target namespace before calling Patch/Update/Get","Read the namespace from the object metadata: obj.GetNamespace(), and default it explicitly if empty","Verify the kind really is namespace-scoped (some kinds like ClusterRole look similar to namespaced Role) and that your namespace defaulting logic runs","If the namespace should come from a flag/config, propagate it into every NamespacedName built by your code"],"exampleFix":"// before\nnn := types.NamespacedName{Name: \"my-deploy\"}\nclient.Get(ctx, gvk, nn)\n// after\nnn := types.NamespacedName{Name: \"my-deploy\", Namespace: \"kube-system\"}\nclient.Get(ctx, gvk, nn)","handlingStrategy":"validation","validationCode":"func ensureNamespace(gvk schema.GroupVersionKind, nn types.NamespacedName) error {\n\tswitch gvk.Group + \"/\" + gvk.Kind {\n\tcase \"apps/Deployment\", \"v1/Service\", \"v1/Secret\", \"v1/ConfigMap\", \"v1/Pod\":\n\t\tif nn.Namespace == \"\" {\n\t\t\treturn fmt.Errorf(\"kind %s requires a namespace; got empty\", gvk.Kind)\n\t\t}\n\t}\n\treturn nil\n}","typeGuard":"func hasNamespace(nn types.NamespacedName) bool {\n\treturn nn.Namespace != \"\"\n}","tryCatchPattern":"obj, err := client.Get(ctx, gvk, nn)\nif err != nil {\n\tif strings.Contains(err.Error(), \"namespace was not provided\") {\n\t\treturn fmt.Errorf(\"programming error: set nn.Namespace for %s\", gvk)\n\t}\n\treturn err\n}","preventionTips":["Always construct NamespacedName from obj.GetNamespace() rather than a fresh struct","Default namespaces explicitly at manifest parse time, not at API-call time","Use the RESTMapper to check scope before building the client","Add unit tests asserting namespace is set for all namespaced kinds"],"tags":["kubernetes","namespace","validation"],"backgroundTag":"missing-namespace-for-namespaced-resource","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"}