The short answer
GitHub’s Ubuntu 26.04 runner image ships Helm 4.3.0, where the 24.04 image had Helm 3.22.0, and ubuntu-latest moves to 26.04 between 19 October and 19 November 2026. A deploy job that never chose a Helm version will start running Helm 4.
Most charts keep working. The changes Helm documents as breaking fail loudly: a post-renderer script, a registry login with a path. The dangerous ones are quiet. Since 4.2.0, null values in values.yaml can be dropped, so a subchart default you deliberately erased comes back, or entries you left empty are not rendered. Those are still open in Helm 4.3.1.
The Helm 3 behaviour on this page was reproduced on Helm 3.18.2. Helm 4 is not installed here, so the Helm 4 behaviour comes from the Helm documentation, the Helm source at v4.3.1, and issue reports with their reproducers. Each item says which.
Which Helm do you have?
Locally, or as a step in the job that deploys:
Compare before you switch
The regressions change rendered manifests, not exit codes, so the reliable check is to render the same chart with the same values through both versions and read the difference. Run it for each environment’s values files.
A difference in securityContext, resources or a missing block is most likely one of the null regressions below. No difference does not cover server-side apply, which only shows against a cluster.
Symptom to change
| You see | Change |
|---|
| Rendered manifests suddenly contain values you deliberately erased: runAsUser: 472 or 65534 back in a securityContext, a CPU limit you removed. On OpenShift, where such charts are told to null the UID out, the pods can then be refused for running as a UID the namespace does not allow. | A null in the parent chart no longer removes a subchart default |
| A range over a map in values.yaml skips entries left empty, so some applications, users or hosts are simply not rendered. .Values | toJson no longer shows the key. | Keys whose value is null disappear from .Values |
| The release renders with chart defaults as if your -f file was never passed, with no error. Usually a compact, generated JSON values file. | A values file ending on a 4096-byte boundary was silently ignored |
| helm install or upgrade with --wait (or --rollback-on-failure, which turns waiting on) never finishes: it logs waiting for resource … kind=Rollout expectedStatus=Current actualStatus=Unknown until --timeout, although the Rollout is healthy. | --wait hangs until the timeout on custom resources such as Argo Rollouts |
| Deploy steps that pass a path to a script, often a kustomize wrapper, to --post-renderer fail. | --post-renderer takes a plugin name, not a script |
| A login written with a path after the registry host stops working. | helm registry login takes the host name only |
| Installing a new release where another controller or tool already manages some fields can now fail with a field-ownership conflict, where Helm 3 overwrote them. | New releases are installed with server-side apply |
| Pipelines print a deprecation warning for --atomic or --force. | --atomic and --force are renamed |
| A Grafana gridPos pasted into values loses its y, and --set gridPos.y=9 adds a second key instead of overriding. | Not new: keys written y, yes, on, n, no or off become true or false |
Pin Helm in GitHub Actions
Choosing the version yourself means the image change cannot choose it for you. With azure/setup-helm:
Teams hit by the null regressions report pinning Helm 4.1.4, the last release before them. Pinning trades one risk for another: an old version stops receiving fixes, so put a date on the pin and revisit it when a Helm release includes the fixes for #32132 and #32530.
Do not “fix” a dropped runAsUser: null by accepting whatever the subchart renders. The default it reinstates may be a UID your platform refuses, or one you removed on purpose.
Where to go next