Repository navigation
Description
What happened?
When a resource is transferred from one release to another using --take-ownership, and then the original release is upgraded to a version that no longer includes that resource, helm deletes the resource from the cluster — even though it is now owned by a different release.
This was recently fixed for the uninstall case in PR #31584 (which resolved #31333), where verifyOwnershipBeforeDelete now correctly skips resources not owned by the release being uninstalled. However, the upgrade path has no equivalent ownership check.
When helm computes the diff between old and new manifests during upgrade, it deletes orphaned resources based solely on whether helm.sh/resource-policy: keep is present — it does not check meta.helm.sh/release-name or meta.helm.sh/release-namespace.
The deletion happens in pkg/kube/client.go in the update() function (around line 647):
for _, info := range originals.Difference(targets) {
// ...
if annotations != nil && annotations[ResourcePolicyAnno] == KeepPolicy {
continue
}
if err := deleteResource(info, metav1.DeletePropagationBackground); err != nil {This checks helm.sh/resource-policy: keep but does not check meta.helm.sh/release-name. Adding an ownership check here (similar to verifyOwnershipBeforeDelete in the uninstall path) would complete the feature.
What did you expect to happen?
When upgrading release-a to a version that no longer includes a resource, helm should check the live ownership annotations before deleting. If meta.helm.sh/release-name on the resource points to a different release (e.g. release-b), it should skip deletion — the same way helm uninstall now does after PR #31584.
How can we reproduce it (as minimally and precisely as possible)?
# Create two simple charts:
# chart-a-v1: contains ConfigMap "shared-config" + ConfigMap "chart-a-own"
# chart-a-v2: contains only ConfigMap "chart-a-own" (shared-config removed)
# chart-b-v1: contains ConfigMap "shared-config" + ConfigMap "chart-b-own"
# Step 1: Install chart-a v1
helm install release-a ./chart-a-v1 -n test
# Step 2: Install chart-b, adopting shared-config
helm install release-b ./chart-b-v1 -n test --take-ownership
# Verify ownership transferred:
kubectl get configmap shared-config -n test -o jsonpath='{.metadata.annotations}'
# {"meta.helm.sh/release-name":"release-b","meta.helm.sh/release-namespace":"test"}
# Step 3: Upgrade release-a to v2 (removes shared-config from its manifest)
helm upgrade release-a ./chart-a-v2 -n test
# Result: shared-config is DELETED, even though release-b owns it
kubectl get configmap shared-config -n test
# Error from server (NotFound): configmaps "shared-config" not foundFor contrast, uninstall works correctly:
# (same setup as above, steps 1-2)
helm uninstall release-a -n test
# level=WARN msg="skipping delete of resource not owned by this release" kind=ConfigMap name=shared-config
# 1 resource(s) were not deleted because they are not owned by this release:
# [ConfigMap] shared-config
# shared-config survives
kubectl get configmap shared-config -n test
# NAME DATA AGE
# shared-config 2 30s
``
### Helm version
<details>
```console
$ helm version
version.BuildInfo{Version:"v4.2.0", GitCommit:"06468084e85c244c712834933d25ea232a4c2093", GitTreeState:"clean", GoVersion:"go1.26.3", KubeClientVersion:"v1.36"}Kubernetes version
Details
$ kubectl version
Client Version: v1.35.2
Server Version: v1.35.0
Activity
cg49996w11 commentedon Jun 21, 2026
@mark007 , I want to work on this issue. Please assign it to me
cg49996w11 commentedon Jun 21, 2026
/assign
venom02 commentedon Jul 7, 2026
yes please, i am blocked too with this take-ownership broken feature
mark007 commentedon Sep 15, 2026
Thanks for assigning this @cg49996w11 . May I ask if the pull request you created looks to be working, does it just need a code review or is further work required? Many thanks.
silence-coding commentedon Oct 21, 2026
I've opened #32793 as an alternative fix for this issue.
It applies the same ownership check to the delete phase of
Update(pkg/kube/client.go), so a resource that has been adopted by another release (via--take-ownership) is no longer deleted when the source release is upgraded/rolled back.Differences from the stalled draft #32257:
Updatecall sites — upgrade, rollback, and install — not just upgrade. They share the sameupdate()delete loop.meta.helm.sh/release-name(notrelease-namespace) to avoid edge-case false skips for cluster-scoped or cross-namespace resources.ClientUpdateOptionOwnership(releaseName)option (single param) and wires it from the three action call sites.Verified on a k3s cluster with fixed vs. unmodified builds:
--take-ownership, upgrade A removes): fixed build keeps the resource; unmodified deletes it.Unit + integration test details are in the PR description. Happy to adjust based on maintainer feedback.
fix: check ownership before delete in upgrade/rollback/install
fix: check ownership before delete in upgrade/rollback/install
fix: check ownership before delete in upgrade/rollback/install