Helm "UPGRADE FAILED: cannot patch ... field is immutable"
By Kaveh Alemi·Latchkey
Helm upgrades by patching existing objects. When a chart change touches an immutable field - a Deployment selector, a Job template, a Service clusterIP - the API server rejects the patch, and Helm reports cannot patch ... field is immutable.
What this error means
helm upgrade fails with Error: UPGRADE FAILED: cannot patch "<name>" with kind <Kind>: <Kind> "<name>" is invalid: spec.<field>: Invalid value: ...: field is immutable.
helm output
Error: UPGRADE FAILED: cannot patch "api" with kind Deployment:
Deployment.apps "api" is invalid: spec.selector: Invalid value: ...:
field is immutable
Diagnose it: render the chart before you install it
Most Helm failures are visible in the rendered manifests. Template them locally with the same values CI uses and you will usually see the problem without touching the cluster.
Terminal
# what will actually be applied
helm template <release> <chart> -f values.ci.yaml | head -60
# validate against the live cluster schema without installing
helm install <release> <chart> -f values.ci.yaml --dry-run --debug
# what state is the release actually in?
helm history <release>
helm status <release>
Common causes
Chart changed an immutable selector/template
Editing spec.selector.matchLabels (Deployment/StatefulSet) or a Job’s spec.template in the chart produces a patch the API server forbids on the existing object.
Service clusterIP or other locked field changed
A change to Service.spec.clusterIP or another field fixed at creation cannot be patched in place during the upgrade.
How to fix it
Recreate the object instead of patching it
For immutable fields, delete the conflicting resource so the next Helm upgrade re-creates it with the new spec.
Terminal
kubectl delete deployment api -n <ns>
helm upgrade --install api ./chart -n <ns>
Keep immutable fields stable in the chart
Never change spec.selector labels on an existing Deployment/StatefulSet via the chart.
For Jobs, render a new name (e.g. include a hash) so each run is a new object.
Diff before upgrading: helm diff upgrade (helm-diff plugin) to catch immutable changes.
How to prevent it
Decide selector labels once and keep them constant across chart versions.
Use helm diff upgrade in CI to catch immutable-field changes before they fail.
Recreate (blue/green) rather than mutate when an immutable field must change.
Frequently asked questions
What causes Helm "UPGRADE FAILED: cannot patch ... field is immutable"?
There are 2 common causes: chart changed an immutable selector/template and service clusterip or other locked field changed. Editing spec.selector.matchLabels (Deployment/StatefulSet) or a Job’s spec.template in the chart produces a patch the API server forbids on the existing object.
How do I fix Helm "UPGRADE FAILED: cannot patch ... field is immutable"?
There are 2 fixes depending on which cause you have: recreate the object instead of patching it and keep immutable fields stable in the chart. Work through them in order, since the first is the most common.
What does Helm "UPGRADE FAILED: cannot patch ... field is immutable" actually mean?
helm upgrade fails with Error: UPGRADE FAILED: cannot patch "<name>" with kind <Kind>: <Kind> "<name>" is invalid: spec.<field>: Invalid value: ...: field is immutable.
How do I stop Helm "UPGRADE FAILED: cannot patch ... field is immutable" happening again?
Decide selector labels once and keep them constant across chart versions. The prevention section lists 3 changes that keep it from recurring.