GoogleContainerTools/skaffold · error

patching resource %q: %w

Error message

patching resource %q: %w

What it means

The cluster-scoped (non-namespaced) branch of updateRuntimeObject patches the resource via Resource(gvr).Patch without a namespace. This error wraps API server rejections or transport failures for that cluster-scoped patch — e.g. Nodes, ClusterRoles, or CRDs being labeled.

Source

Thrown at pkg/skaffold/deploy/label/labels.go:126

		if accessor.GetNamespace() != "" {
			namespace = accessor.GetNamespace()
		} else {
			namespace = res.Namespace
		}

		ns, err := resolveNamespace(namespace, kubeContext)
		if err != nil {
			return fmt.Errorf("resolving namespace: %w", err)
		}

		log.Entry(ctx).Debug("Patching", name, "in namespace", ns)
		if _, err := client.Resource(gvr).Namespace(ns).Patch(ctx, name, types.StrategicMergePatchType, p, metav1.PatchOptions{}); err != nil {
			return fmt.Errorf("patching resource %s/%q: %w", ns, name, err)
		}
	} else {
		log.Entry(ctx).Debug("Patching", name)
		if _, err := client.Resource(gvr).Patch(ctx, name, types.StrategicMergePatchType, p, metav1.PatchOptions{}); err != nil {
			return fmt.Errorf("patching resource %q: %w", name, err)
		}
	}

	return nil
}

func resolveNamespace(ns, kubeContext string) (string, error) {
	if ns != "" {
		return ns, nil
	}
	cfg, err := kubectx.CurrentConfig()
	if err != nil {
		return "", fmt.Errorf("getting kubeconfig: %w", err)
	}

	current, present := cfg.Contexts[kubeContext]
	if present && current.Namespace != "" {
		return current.Namespace, nil

View on GitHub (pinned to a1189de023)

Solutions

  1. Check `kubectl auth can-i patch <cluster-scoped-resource>` and grant a ClusterRole with patch if denied
  2. Confirm the object exists: `kubectl get <resource> <name>`
  3. Check connectivity with `kubectl cluster-info` and retry if transient
  4. Ensure the manifest's apiVersion matches a served cluster-scoped resource
Defensive patterns

Strategy: retry

Validate before calling

allowed, err := authClient.SelfSubjectAccessReviews().Create(ctx,
    &authv1.SelfSubjectAccessReview{Spec: authv1.SelfSubjectAccessReviewSpec{
        ResourceAttributes: &authv1.ResourceAttributes{Verb: "patch", Resource: resource}}}])

Try / catch

if _, err := client.Resource(gvr).Patch(ctx, name, types.StrategicMergePatchType, p, metav1.PatchOptions{}); err != nil {
    if apierrors.IsNotFound(err) { return nil }
    if apierrors.IsForbidden(err) { return fmt.Errorf("needs cluster-level patch rights on %s: %w", gvr.Resource, err) }
    return retryable(err)
}

Prevention

When it happens

Trigger: Patching a cluster-scoped object fails: RBAC denies patch on cluster-scoped resources, object not found, conflict, or API server/network error.

Common situations: CI ServiceAccount without cluster-level patch rights; user lacks cluster-admin for the resource kind; resource removed concurrently; ephemeral cluster connectivity issues.

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/17d74b0293a9ca24. Report an issue: GitHub.