Originally published on DevToolHub.
If your terraform plan started throwing schema errors after a routine provider update, you're probably looking at the Terraform Helm provider migration from v2 to v3. HashiCorp rewrote the provider on top of the Terraform Plugin Framework in v3.0.0, and it changed how you write set, kubernetes, and registry configuration — not just internally, but in your actual .tf files.
The latest release is v3.2.0, published June 4, 2026. Here's exactly what changed, the before/after syntax, and the state upgrade errors people are hitting in the GitHub issue tracker.
What the Terraform Helm Provider Migration Changed
Three things break when you jump from v2.x to v3.x:
-
set,set_list, andset_sensitiveinsidehelm_releaseandhelm_templatego from repeatable blocks to a single list attribute of nested objects. - The
kubernetesblock on the provider becomes a single object attribute (kubernetes = { ... }instead ofkubernetes { ... }). - The
registryblock — which used to support multiple repeated blocks — becomes aregistrieslist attribute.
None of these are cosmetic. Terraform's plugin framework handles blocks and list-of-object attributes differently in state, which is why a straight version bump without touching your HCL will fail to plan.
Why HashiCorp Migrated to the Plugin Framework
The old provider ran on Terraform Plugin SDKv2, which HashiCorp has been retiring across its provider ecosystem in favor of the newer Plugin Framework. The framework uses Terraform Plugin Protocol Version 6, compatible with Terraform 1.0 and above, and gives providers more precise control over schema validation and state handling than SDKv2 allowed.
For the Helm provider specifically, that meant converting the repeatable-block pattern (common in SDKv2-era providers) into list attributes, which the framework models more cleanly. It's the same category of change other HashiCorp providers have gone through — annoying for a version bump, but not unique to Helm.
Migrating set, set_list, and set_sensitive Blocks
This is the change you'll hit in almost every helm_release resource. Before v3, you wrote repeated set blocks:
resource "helm_release" "example" {
name = "my-release"
chart = "my-chart"
set {
name = "service.type"
value = "ClusterIP"
}
}
In v3, set is a list of objects instead:
resource "helm_release" "example" {
name = "my-release"
chart = "my-chart"
set = [
{
name = "service.type"
value = "ClusterIP"
}
]
}
The same conversion applies to set_list and set_sensitive — both change from repeated blocks to list-of-object attributes, in both helm_release resources and the helm_template data source. If you have five set blocks in a release today, they collapse into one set = [...] attribute with five entries.
Migrating the kubernetes and registry Blocks
The provider-level configuration changes too. kubernetes goes from a block to a single object:
# Before — v2.x
provider "helm" {
kubernetes {
config_path = "~/.kube/config"
}
}
# After — v3.x
provider "helm" {
kubernetes = {
config_path = "~/.kube/config"
}
}
registry is the trickier one, because it wasn't just a block-to-object change — it also went from singular to plural, since the provider supports multiple registries:
# Before — v2.x
provider "helm" {
registry {
url = "oci://localhost:5000"
username = "username"
password = "password"
}
}
# After — v3.x
provider "helm" {
registries = [
{
url = "oci://localhost:5000"
username = "username"
password = "password"
}
]
}
If you had multiple registry blocks before, they all move into the same registries list, one object per entry.
State Upgrade Errors During the Terraform Helm Provider Migration
Two issues show up repeatedly in the terraform-provider-helm GitHub tracker. The first: existing state written under v2.x sometimes isn't read correctly after upgrading to v3, because the state upgrader doesn't always cleanly translate the old block-based schema into the new object/list schema. The second, tracked separately, is the provider failing to upgrade resource state to v3 at all in certain configurations.
HashiCorp shipped a hotfix in v3.0.1 (the same day as v3.0.0) specifically for a state upgrader bug affecting the values attribute type — so if you hit an error mentioning values, make sure you're on at least v3.0.1, not v3.0.0.
⚠️ Note: Run terraform plan in a non-production workspace first after the upgrade. If the plan shows unexpected diffs on resources you didn't touch, that's usually the state upgrader mismatch, not a real infrastructure drift. Don't apply until the plan is clean.
Should You Run the Terraform Helm Provider Migration Now
If you're still pinned to a 2.x version, there's no forced deadline, but 2.x isn't getting new features — the changelog shows all active development going into 3.x since mid-2025. The safer path is a deliberate migration rather than an accidental one: pin your provider version explicitly, do the HCL rewrite in a branch, and test the plan against a non-production state before rolling it into your main branch.
If you've already been through a Helm 4 migration on the chart side, this is a smaller lift by comparison — it's syntax, not runtime behavior. The version history since 3.0.0 has been mostly bug fixes and small additive features, not further breaking changes:
- v3.0.0 (June 18, 2025) — the breaking migration itself
-
v3.0.1 (June 18, 2025) — state upgrader hotfix for
values - v3.0.2 (June 23, 2025) — fixed plan errors on version specs, postrender execution, sensitive value redaction
-
v3.1.0 (Oct 27, 2025) — added
qps,resources,set_wo,take_ownership, configurable operation timeouts - v3.1.1 (Nov 17, 2025) — fixed an "inconsistent result after apply" error
- v3.1.2 (May 21, 2026) — Windows OCI chart fix, dependency updates
-
v3.2.0 (June 4, 2026) — added a
linux/s390xbuild target for IBM Z platforms
Nothing after 3.0.x changes your HCL syntax again — once you've done the initial migration, later upgrades are safe minor bumps.
Frequently Asked Questions
Q: Do I have to migrate to Terraform Helm provider v3?
A: Not immediately, but v2.x isn't receiving new features. If you're managing Helm deployments long-term, plan the migration on your own schedule rather than waiting for a forced upgrade.
Q: My set blocks are gone after upgrading — did I lose configuration?
A: No, but you need to rewrite them as a set = [...] list attribute. The provider won't auto-convert set { } blocks in your .tf files — that part is manual.
Q: What Terraform version does v3 require?
A: 1.0 and above, since it runs on Terraform Plugin Protocol Version 6.
Q: I'm getting a "values" attribute error after upgrading — what's wrong?
A: You're likely on v3.0.0 exactly. Upgrade to at least v3.0.1, which shipped a same-day hotfix for this state upgrader issue.
Quick Summary:
- Terraform Helm provider v3.0.0 (June 18, 2025) rewrote the provider on the Plugin Framework, requiring Terraform 1.0+
-
set,set_list, andset_sensitivechange from repeated blocks to a single list-of-objects attribute -
kubernetesbecomes an object attribute;registrybecomes a pluralregistrieslist - State upgrade errors are common — check GitHub issues #1722 and #1698 if resources don't read correctly post-upgrade
- Latest version is v3.2.0 (June 4, 2026); no further HCL syntax changes since the 3.0.0 migration
Pin your provider version explicitly before you touch anything, then do the HCL rewrite in a branch you can terraform plan against before merging.
Top comments (0)