kubernetes/kops · error

namespace was not provided for namespace-scoped object %v

Error message

namespace was not provided for namespace-scoped object %v

What it means

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.

Source

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

		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

	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) {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Set nn.Namespace to the target namespace before calling Patch/Update/Get
  2. Read the namespace from the object metadata: obj.GetNamespace(), and default it explicitly if empty
  3. Verify the kind really is namespace-scoped (some kinds like ClusterRole look similar to namespaced Role) and that your namespace defaulting logic runs
  4. If the namespace should come from a flag/config, propagate it into every NamespacedName built by your code

Example fix

// before
nn := types.NamespacedName{Name: "my-deploy"}
client.Get(ctx, gvk, nn)
// after
nn := types.NamespacedName{Name: "my-deploy", Namespace: "kube-system"}
client.Get(ctx, gvk, nn)
Defensive patterns

Strategy: validation

Validate before calling

func ensureNamespace(gvk schema.GroupVersionKind, nn types.NamespacedName) error {
	switch gvk.Group + "/" + gvk.Kind {
	case "apps/Deployment", "v1/Service", "v1/Secret", "v1/ConfigMap", "v1/Pod":
		if nn.Namespace == "" {
			return fmt.Errorf("kind %s requires a namespace; got empty", gvk.Kind)
		}
	}
	return nil
}

Type guard

func hasNamespace(nn types.NamespacedName) bool {
	return nn.Namespace != ""
}

Try / catch

obj, err := client.Get(ctx, gvk, nn)
if err != nil {
	if strings.Contains(err.Error(), "namespace was not provided") {
		return fmt.Errorf("programming error: set nn.Namespace for %s", gvk)
	}
	return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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