LearnDevOpsHands-On Labs
Troubleshooting Matrix/Error: rendered manifests contain a resource that already exists
LinuxHigh Severity

Error: rendered manifests contain a resource that already exists

Fix Helm "rendered manifests contain a resource that already exists": add Helm ownership labels and annotations to adopt it, or delete it. Covers CRDs.

Observed Error Signature / Log Pattern
Error: INSTALLATION FAILED: Unable to continue with install: ConfigMap "app-config" in namespace "production" exists and

Incident Overview

Fix Helm "rendered manifests contain a resource that already exists": add Helm ownership labels and annotations to adopt it, or delete it. Covers CRDs.

medium fix·5 min read

By Vishvesh Patel·DevOps Engineer·Updated 21 September 2026

BASHDiagnostic / remediation command
Error: INSTALLATION FAILED: Unable to continue with install: ConfigMap "app-config" in namespace "production" exists and cannot be imported into the current release: invalid ownership metadata; label validation error: missing key "app.kubernetes.io/managed-by": must be set to "Helm"

Error: rendered manifests contain a resource that already exists. Unable to continue with install: Service "api" in namespace "production" exists and cannot be imported into the current release

Do this first3 steps

Run these in order. Each one tells you what its output means before you change anything.

• Read the message, it names the exact object and the missing metadata

Helm checks one label and two annotations. Whichever the error names is the one absent or wrong, and that is all it is complaining about.

• Adopt the object by adding the ownership metadata Helm expects

Helm then treats the object as part of the release and will update it in place. This is the non-destructive option and works for resources holding data you cannot recreate.

• Or delete it and let Helm create it, when it holds nothing you need

Safe for generated config and Services. Not safe for a PersistentVolumeClaim or a Secret you cannot regenerate, where adopting is the right call.

Helm refuses to take over an object it did not create. This is deliberate: silently adopting resources would let a chart claim and then delete things belonging to something else.

Helm identifies its own objects by three pieces of metadata:

All three must match. The error names whichever is missing or wrong.

BASHDiagnostic / remediation command
kubectl get configmap app-config -n production -o jsonpath='{.metadata.labels}{"\n"}{.metadata.annotations}{"\n"}'

Look at the object

No Helm metadata at all, so it was created with kubectl apply or by another tool.

BASHDiagnostic / remediation command
kubectl get configmap app-config -n production \
  -o jsonpath='{.metadata.labels}{"\n"}{.metadata.annotations}{"\n"}'

Option 1: Adopt it

Non-destructive, and the right choice for anything holding data:

Then re-run the install. Helm now recognises the object and updates it in place.

For several objects at once:

Be careful with a loop like that on a shared namespace: it claims everything it touches for the release, and a later helm uninstall will then delete all of it. Scope it with a label selector.

The release-namespace annotation must be the namespace the release lives in, which is not always the object's namespace for cluster-scoped resources. A ClusterRole belonging to a release in production still gets meta.helm.sh/release-namespace: production.

BASHDiagnostic / remediation command
kubectl label configmap app-config -n production \
  app.kubernetes.io/managed-by=Helm --overwrite

kubectl annotate configmap app-config -n production \
  meta.helm.sh/release-name=api \
  meta.helm.sh/release-namespace=production --overwrite

Option 2: Delete and let Helm create it

Fine for generated config, Services and Deployments. Not fine for:

For those, adopt rather than delete.

BASHDiagnostic / remediation command
kubectl delete configmap app-config -n production
helm upgrade --install api ./chart -n production

How this happens

Migrating from kubectl to Helm. Objects were applied by hand and the chart now defines the same names. Adoption is the intended path.

Two charts defining the same object. Often a subchart and a parent both rendering a ServiceAccount or a ConfigMap. Disable one:

A previous uninstall left objects behind. Anything annotated helm.sh/resource-policy: keep survives helm uninstall by design, and then blocks a fresh install. That annotation is deliberate for PVCs and CRDs, so removing the object is a decision, not a cleanup.

A namespace created by --create-namespace then reused. The Namespace object itself is not owned by the release, which is usually what you want.

BASHDiagnostic / remediation command
# values.yaml
subchart:
  serviceAccount:
    create: false
    name: shared-sa

CRDs are different

Custom Resource Definitions in a chart's crds/ directory are installed before templates render and are never upgraded or deleted by Helm. A CRD installed by one chart blocks another chart that also ships it:

The usual answer is to install the CRDs once, out of band, and disable them in both charts:

BASHDiagnostic / remediation command
kubectl get crd certificates.cert-manager.io \
  -o jsonpath='{.metadata.annotations}'

Finding the conflict before it happens

A server-side dry run validates against the live cluster and reports conflicts without changing anything. Worth running in CI before a first install into an environment that was previously managed another way.

helm template alone does not do this, because it never talks to the cluster.

BASHDiagnostic / remediation command
helm install api ./chart -n production --dry-run=server

A checklist

Frequently Asked Questions

Why will Helm not just take over an existing resource?

Because adopting silently would let any chart claim objects it did not create, and a later helm uninstall would then delete them. Helm therefore requires explicit ownership metadata: the label app.kubernetes.io/managed-by: Helm plus the annotations meta.helm.sh/release-name and meta.helm.sh/release-namespace. Setting them by hand is you stating that this object really does belong to that release, which is exactly the confirmation the check is asking for.

Is it safe to delete the conflicting resource?

It depends entirely on what it is. Deleting a ConfigMap, Service or Deployment that the chart will immediately recreate is usually harmless. Deleting a PersistentVolumeClaim can destroy the underlying volume depending on the StorageClass reclaim policy, deleting a Secret you cannot regenerate loses it, and deleting a LoadBalancer Service typically means a new external IP, which breaks DNS until it propagates. For any of those, adopt the object instead.

How do I migrate resources created with kubectl into a Helm release?

Add the ownership metadata to each object, then run helm upgrade --install. Helm recognises them and manages them from then on. Two cautions: apply the metadata only to objects that genuinely belong to the release, because anything you label becomes something helm uninstall will delete; and for cluster-scoped resources, the meta.helm.sh/release-namespace annotation must name the namespace the release lives in, not the object's namespace, since it has none.

Why does this happen with CRDs specifically?

Because CRDs in a chart's crds/ directory are installed before templates are rendered, and Helm deliberately never upgrades or deletes them, since doing so would destroy every custom resource in the cluster. So a CRD installed by one chart remains, unowned by any release, and blocks a second chart that also ships it. The standard resolution is to install CRDs once out of band and set the chart's installCRDs value, or its equivalent, to false in every chart that would otherwise provide them.

How can I catch these conflicts before running a real install?

Use helm install --dry-run=server, which renders the chart and validates it against the live cluster, reporting ownership conflicts without changing anything. helm template does not help here, because it renders locally and never contacts the cluster, so it cannot know what already exists. Running the server-side dry run in CI before the first install into an environment previously managed by kubectl turns this from a failed deployment into a build-time warning.

Reference and practice

Learn the underlying concept

Other Helm errors

Free, comprehensive DevOps tutorials and learning roadmaps. Master Docker, Kubernetes, CI/CD, and more.

Get notified about new tutorials and features.

• Roadmaps

• Interview Prep

• Certifications

• Company

© 2026 DevOpsLesson. All rights reserved.

Need to practice this scenario?

Simulate this error condition and practice recovery commands safely in our in-browser terminal.

Open Linux Sandbox