Skip to content

ssaForceConflicts fails on releases installed before Helm v4: "forceConflicts enabled when serverSideApply disabled" #403

Closed

Description

@jerryguowei

What happened?

After upgrading provider-helm from v1.0.6 (Helm v3 SDK) to v1.4.x (Helm v4 SDK), any existing Release that has spec.forProvider.ssaForceConflicts: true fails to upgrade:

Upgrade "<release>" failed: invalid client update option(s): forceConflicts enabled when serverSideApply disabled

The Helm release goes to failed and the Release stays Ready=False.

Root cause: pkg/clients/helm/client.go sets ForceConflicts from ssaForceConflicts on the upgrade and rollback actions, but it never sets ServerSideApply. That leaves Helm's default of "auto", which uses server-side apply only when the previous revision's ApplyMethod == "ssa" (helm v4.2.3, pkg/action/upgrade.go getUpgradeServerSideValue). Revisions written by Helm v3 (so by provider-helm <= v1.0.x) have no ApplyMethod, so Helm resolves to client-side apply. Helm then rejects the combination in kube.ClientUpdateOptionServerSideApply (pkg/kube/client.go: if !serverSideApply && forceConflicts { return errors.New(...) }).

As a result, ssaForceConflicts can never be used on releases created before the Helm v4 migration. Fresh installs work, because Helm v4 installs with SSA by default.

This was anticipated in #333: "old release that used client-side apply will continue to do so. We could override this behavior to always prefer SSA with forced conflict resolution by setting ServerSideApply and ForceConflicts on helm actions to true … Maybe it could be introduced behind a spec field e.g. ssaForceConflicts". The field was added in 4e1f8de, but only ForceConflicts is wired.

Expected: with ssaForceConflicts: true, the upgrade (and rollback) switches the release to server-side apply and force-resolves conflicts, including the ones left over from client-side apply field managers.

How can we reproduce it?

  1. Install provider-helm v1.0.6 and create a Release, for example:
    apiVersion: helm.crossplane.io/v1beta1
    kind: Release
    metadata:
      name: example
    spec:
      forProvider:
        chart:
          name: <any-chart>
          repository: <repo>
          version: <v1>
        namespace: default
      providerConfigRef:
        name: helm
    Wait until it is Ready. The Helm release secret for revision 1 has no apply_method.
  2. Upgrade provider-helm to v1.4.x.
  3. Update the Release: bump chart.version and set ssaForceConflicts: true.
  4. The upgrade fails with forceConflicts enabled when serverSideApply disabled.

Proposed fix

When SSAForceConflicts is set, also force SSA on the upgrade and rollback actions:

--- a/pkg/clients/helm/client.go
+++ b/pkg/clients/helm/client.go
@@ uc := action.NewUpgrade(actionConfig)
 	uc.ForceConflicts = args.SSAForceConflicts
+	if args.SSAForceConflicts {
+		// Helm's default "auto" keeps client-side apply for releases that were
+		// installed with it (e.g. by Helm v3), which Helm rejects in combination
+		// with ForceConflicts. Force server-side apply so such releases migrate.
+		uc.ServerSideApply = "true"
+	}
@@ rb := action.NewRollback(actionConfig)
 	rb.ForceConflicts = args.SSAForceConflicts
+	if args.SSAForceConflicts {
+		rb.ServerSideApply = "true"
+	}

This builds, and the pkg/clients/helm unit tests still pass. Happy to open a PR.

Workaround until fixed: patch the latest Helm release secret so its apply_method is "ssa". Helm's "auto" then picks server-side apply.

What environment did it happen in?

  • Crossplane version: v2.3.5
  • provider-helm: xpkg.upbound.io/upbound/provider-helm:v1.4.1 (upgraded from v1.0.6); code is unchanged on main as of 37ce1ab
  • Helm SDK: helm.sh/helm/v4 v4.2.3
  • Kubernetes: v1.36.2+k3s1

Activity

  1. jonasz-lasut commented on Sep 23, 2026

    @jonasz-lasut
    Collaborator

    Hi @jerryguowei thank you for opening the issue. We're open to contributions and this seems like a proper resolution of this issue. I'll have a look when the PR is opened

  2. added a commit that references this issue on Sep 25, 2026
    13202e2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions