When Helm Hits a Wall
Youāre pushing a routine update to production, expecting a green checkmark from your CI/CD pipeline. Instead, the deployment stops dead. Helm throws a specific, frustrating error: rendered manifests contain a resource that already exists. Your release is stuck, and the cluster is in limbo.
Error: UPGRADE FAILED: rendered manifests contain a resource that already exists. Unable to continue with update: existing resource conflict
This conflict occurs when Helm tries to create a resourceālike a ConfigMap, Secret, or Serviceāthat is already present in your namespace but isn't part of the current Helm release. Usually, this happens because someone manually tweaked the cluster using kubectl or a previous installation attempt failed and left orphaned resources behind.
Why Helm Refuses to Proceed
Helm is designed to be overprotective. When you run helm upgrade, it generates YAML manifests and compares them against the live cluster. If it finds a resource with a matching name and kind that lacks the specific metadata (labels and annotations) of the current release, Helm bails out. It assumes the resource belongs to someone else and refuses to overwrite it to prevent accidental data loss.
Youāll typically see this in three scenarios:
- A team member manually ran
kubectl applyfor a quick fix. - A previous
helm installtimed out at the 5-minute mark and crashed. - You are moving resources from a legacy monolithic chart into a new sub-chart.
Step 1: Identify the Culprit
The error message usually identifies the exact resource causing the headache. It might look like this:
Existing resource conflict: kind: Secret, namespace: production, name: app-credentials
Check the current state of that resource to see if itās actually managed by anything:
kubectl get secret app-credentials -n production -o yaml
Scan the metadata section. If you don't see app.kubernetes.io/managed-by: Helm and a meta.helm.sh/release-name annotation, Helm doesn't "own" it. Itās an orphan.
Option A: The Quick Reset (Delete and Recreate)
If the resource is statelessālike a Service or a ConfigMap that doesn't hold critical dataāthe fastest fix is to delete it. Helm will simply recreate it during the next upgrade attempt.
# Delete the conflicting resource
kubectl delete secret app-credentials -n production
# Retry the upgrade
helm upgrade --install my-app ./charts/my-app -n production
Warning: Never do this for PersistentVolumeClaims or Secrets containing unique production keys (like RDS passwords) unless you have a verified backup.
Option B: Adopting Resources into Helm
Sometimes you can't afford a second of downtime. In this case, you need to "teach" Helm that it owns the existing resource. You do this by manually applying the labels and annotations Helm expects to see.
Run these commands to tag your existing resource:
# Define your variables
RELEASE_NAME="my-app"
NAMESPACE="production"
RESOURCE_KIND="secret"
RESOURCE_NAME="app-credentials"
# Add the required annotations
kubectl annotate $RESOURCE_KIND $RESOURCE_NAME -n $NAMESPACE meta.helm.sh/release-name=$RELEASE_NAME
kubectl annotate $RESOURCE_KIND $RESOURCE_NAME -n $NAMESPACE meta.helm.sh/release-namespace=$NAMESPACE
# Add the required label
kubectl label $RESOURCE_KIND $RESOURCE_NAME -n $NAMESPACE app.kubernetes.io/managed-by=Helm
Once tagged, run helm upgrade again. Helm will recognize the resource as its own and update it seamlessly.
Fixing "Another Operation in Progress"
If your previous attempt was interrupted (perhaps a CI runner timed out after 300 seconds), you might see a secondary error: another operation is in progress. Helm thinks a deployment is still running and locks the release state to pending-upgrade.
To break this lock, you must find and delete the Secret Helm uses for tracking that specific failed attempt. These are usually named sh.helm.release.v1.[RELEASE_NAME].v[VERSION].
# List all release versions to find the highest number
kubectl get secrets -n production | grep sh.helm.release.v1.my-app
# Delete the secret for the 'pending' version (e.g., v15)
kubectl delete secret sh.helm.release.v1.my-app.v15 -n production
Once that secret is gone, Helm reverts to the last successful version (e.g., v14), and you can try your upgrade again.
Verification and Prevention
After your fix, confirm the release is healthy:
- Run
helm status my-app -n production. Look forSTATUS: deployed. - Verify the metadata:
kubectl get secret app-credentials -n production -o jsonpath='{.metadata.labels}'. It should show the Helm management label.
To avoid this in the future, always use the --atomic flag in your pipelines. This ensures that if a deployment fails, Helm automatically rolls back to the previous stable state, preventing your releases from getting stuck in a pending loop.

