Helm 4.3.0 came out on September 9, 2026, and the first patch, 4.3.1, followed on October 15. Together they make up the current Helm release. The headline items are small on paper. There are new template functions for durations, a reason field for rollbacks and a history column that shows where a rollback went. The change most likely to surprise you is in helm uninstall, which now checks that a resource belongs to the release before deleting it.
The 4.3.1 patch matters too. It fixes a Helm 4 regression where a chart that ships CRDs could fail on install because Helm stopped waiting for the CRDs to be ready. If you install operators with Helm 4 and don't pass --wait, that fix alone is a reason to upgrade.
This article walks through each change, what it means for charts and pipelines, and how to move to 4.3.1. Helm 3.22.0 and 3.22.1 shipped on the same days, but they are mostly dependency updates, and the Helm 4.3 release notes state that no further Helm 3 minor releases are planned.
CRDs are waited for again (4.3.1)
Charts can put CustomResourceDefinitions in a crds/ directory. Helm installs those first, waits for the API server to accept them, then renders and applies the templates, which may contain custom resources of the new kinds. That wait matters because a CRD isn't usable the instant it's created. The API server has to mark it established before it serves the new kind.
Helm 4 introduced wait strategies. Without the --wait flag, the strategy is hookOnly, which waits for hooks and skips waiting for everything else. In 4.0 through 4.3.0 that no-op also applied to the CRD step. A plain helm install could push the CRDs and immediately try to create custom resources that the API server didn't know about yet. The install then failed with a mapping error for the new kind. Whether it hit depended on how fast the API server was, which made the bug look flaky.
In 4.3.1, when the strategy is hookOnly, Helm switches to the watcher strategy for the CRD check only. It waits up to 60 seconds for the CRDs, as Helm 3 always did, and the rest of the release still follows hookOnly. Nothing changes if you already pass --wait or --rollback-on-failure, because both already used watcher.
If you can't upgrade yet, pass --wait on installs of charts with a crds/ directory. That waits for the whole release, which is slower, but it avoids the race.
helm install my-operator ./my-operator \
--namespace operators --create-namespace \
--wait --timeout 10m
Keep in mind that Helm only installs the crds/ directory on the first install. Upgrades never touch those CRDs, so this fix affects helm install and helm upgrade --install on a new release, not routine upgrades.
Uninstall only deletes what the release owns (4.3.0)
Before 4.3, helm uninstall read the manifest stored in the release record and deleted every object listed there, unless it carried the helm.sh/resource-policy: keep annotation. It didn't check whether the live object still belonged to the release.
That gap bites when ownership moves. Helm 3.17 and later have --take-ownership on helm install and helm upgrade, which lets a second release adopt an object the first one created. Teams also split charts, move a ConfigMap from one release to another, or recreate an object by hand. In all of these cases the old release's manifest still lists the object, and uninstalling the old release deleted something another release now depended on.
Helm 4.3 fetches each object before deleting it and checks the same ownership metadata Helm writes on every install and upgrade. The object must have the label app.kubernetes.io/managed-by: Helm, and the annotations meta.helm.sh/release-name and meta.helm.sh/release-namespace must match the release being removed. Objects that pass are deleted. Objects that fail are skipped and listed in the output.
1 resource(s) were not deleted because they are not owned by this release:
[ConfigMap] web-feature-flags
release "web" uninstalled
There is a third case. If Helm can't read the object at all, for example because the service account running the uninstall has delete permission but not get, the ownership can't be verified. Helm 4.3 skips those objects too and prints the error next to each one. This is the change to check in your pipelines. A CI role trimmed to create and delete permissions used to uninstall cleanly and now leaves objects behind. Grant get on the kinds your charts manage.
To see the decision before it happens, run the uninstall as a dry run. It logs a warning for every object it would skip and why.
helm uninstall web -n shop --dry-run
When a skipped object surprises you, look at its ownership metadata directly.
kubectl get configmap web-feature-flags -n shop \
-o jsonpath='{.metadata.labels.app\.kubernetes\.io/managed-by}{" "}{.metadata.annotations.meta\.helm\.sh/release-name}{" "}{.metadata.annotations.meta\.helm\.sh/release-namespace}{"\n"}'
If the release name printed there is a different release, the new behavior just saved you from an outage. If the label or annotations are missing because some other tool rewrote the object, delete it yourself once you're sure nothing uses it.
Rollbacks can carry a reason (4.3.0)
helm rollback gained a --description flag. Until now every rollback revision got the description Rollback to N, which tells you where the release went but not why. When someone reads the history at 3 a.m. during the next incident, the why is what they need.
helm rollback web 4 -n shop \
--description "Revert 2.4.0: checkout p99 latency doubled" \
--wait --timeout 10m
The description is limited to 256 characters, and Helm rejects a longer one before doing anything. If you leave the flag out, you get the old Rollback to N text.
A custom description replaces that text, so the target revision would disappear from the history. To keep it, 4.3 also stores the target revision as a separate field on the release, rollback_revision. The table output hides it unless you ask for the new column.
helm history web -n shop --show-rollback-revision
REVISION UPDATED STATUS CHART APP VERSION ROLLBACK DESCRIPTION
4 Tue Nov 3 16:40:02 2026 superseded web-1.4.1 2.3.1 Upgrade complete
5 Wed Nov 4 09:05:17 2026 superseded web-1.5.0 2.4.0 Upgrade complete
6 Wed Nov 4 11:31:50 2026 deployed web-1.4.1 2.3.1 4 Revert 2.4.0: checkout p99 latency doubled
JSON and YAML output include rollback_revision for rollback revisions without any flag, which is the easier format for scripts and dashboards. The field is new in 4.3, so rollbacks made with an older Helm leave it empty. For those, the description is still the only record.
Duration functions in templates (4.3.0)
Charts often take a time value once and need it in several units. A shutdown timeout ends up in terminationGracePeriodSeconds as an integer of seconds, in an environment variable in milliseconds, and maybe in a flag as a Go duration string. Before 4.3 you either asked users for each unit separately or did the arithmetic with Sprig math functions and hoped nobody wrote "1m".
Helm 4.3 adds a family of duration helpers to the template engine. durationSeconds, durationMinutes, durationHours, durationDays and durationWeeks return floats. durationMilliseconds, durationMicroseconds and durationNanoseconds return integers. durationRoundTo and durationTruncateTo round a duration to a multiple of another, and mustToDuration parses a value into a duration or fails the render.
The input is flexible. A string such as "90s" or "1h30m" is parsed as a Go duration. A bare number, or a numeric string such as "2.5", is treated as seconds. That means a values file can accept both shutdownTimeout: 45 and shutdownTimeout: "45s".
# values.yaml
shutdownTimeout: "45s"
cacheTTL: "2h"
# templates/deployment.yaml (excerpt)
spec:
template:
spec:
terminationGracePeriodSeconds: {{ .Values.shutdownTimeout | mustToDuration | durationSeconds | int }}
containers:
- name: app
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
env:
- name: CACHE_TTL_MS
value: {{ .Values.cacheTTL | durationMilliseconds | quote }}
The order in the first line matters. Every helper except mustToDuration returns 0 when it can't parse its input, with no error. A typo like "45 s" would render terminationGracePeriodSeconds: 0, and Kubernetes would kill your pods instantly. Putting mustToDuration first turns that typo into a failed render. The int at the end converts the float to the integer Kubernetes expects.
These functions only exist in Helm 4.3 and later. A chart that uses them fails to render on Helm 3 and on earlier Helm 4 releases with an unknown function error. Chart.yaml has no field for a minimum Helm version, so state it in the chart's README and hold off on publishing such a chart to a public repository until your users have upgraded.
Smaller fixes worth knowing
A few other items in 4.3.0 can explain odd behavior you may have seen on 4.2.
The chart loader no longer drops a values file whose size ends exactly on a 4096-byte boundary. It's rare, but a values file that silently vanished from a chart is a miserable thing to debug, so if you ever saw that, this was the cause.
The watcher wait strategy got faster on releases with many objects. The release notes describe concurrent status computation to avoid multi-minute delays, and a resync period lowered from one hour to 3 minutes.
helm package --sign and helm verify now accept a GnuPG keybox file (pubring.kbx) as the keyring. Recent GnuPG versions store keys in that format by default, so you no longer need to export a legacy pubring.gpg first.
When a lookup call in a template returns nothing, Helm 4.3 logs that at debug level. Run with --debug when a template behaves as if an object doesn't exist and you need to know whether the lookup ran against the cluster at all.
Upgrading to 4.3.1
The 4.3 release notes list no breaking changes, and the chart format is unchanged, so the upgrade itself is a binary swap. The official install script takes a version, which is the safer choice in CI than whatever is latest on the day the job runs.
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-4
chmod 700 get_helm.sh
./get_helm.sh --version v4.3.1
helm version --short
The script installs into /usr/local/bin and uses sudo when needed. Pass --no-sudo and set HELM_INSTALL_DIR to put the binary somewhere you own.
Before rolling it out to every pipeline, check three things. First, any automation that uninstalls releases needs get permission on the objects it deletes, or objects will start to pile up. Second, scripts that parse helm uninstall output should expect the new lines listing skipped objects. Third, if you plan to use the duration functions, upgrade every Helm that renders your charts first, including tools that embed the Helm library to render charts, such as Argo CD and Flux.
The release notes schedule Helm 4.4.0 for January 13, 2027. Until then 4.3.1 is the version to run, and if your charts ship CRDs it's the first Helm 4 release where you can drop the --wait workaround.