Argo CD application stays OutOfSync after sync: find the real diff
Diagnose an Argo CD application that remains OutOfSync by inspecting live-versus-desired diffs, generated fields, mutating controllers, Helm output, and ownership.
Published
Problem
Argo CD reports a successful sync, but the Application immediately returns to OutOfSync. Repeating the sync applies the same manifests without reaching a stable desired state.
Quick answer
Inspect the exact desired-versus-live difference before enabling auto-sync or adding ignore rules:
bash
argocd app get <application> --refresh
argocd app diff <application>
kubectl get <kind> <name> -n <namespace> -o yamlDetermine who changes the field after Argo CD applies it. Typical writers include admission webhooks, operators, HorizontalPodAutoscalers, defaulting by the Kubernetes API, and another GitOps controller.
Confirm the rendered desired state
The source in Git is not always the final manifest. Helm values, Kustomize overlays, plugins, and ApplicationSet parameters can produce a different result:
bash
argocd app manifests <application>Compare that output with the live object. Check the selected revision, chart version, values files, namespace, and destination cluster. A correct file in the wrong overlay does not change the desired state of this Application.
Common causes
Another controller owns the field
An HPA changes spec.replicas; an operator may rewrite its managed custom resource; a webhook can inject labels, annotations, sidecars, or defaults. Decide which controller should own the field rather than making both continuously overwrite it.
List ordering or defaulted values differ
Some controllers reorder lists or materialize default values. The resource may behave correctly while its serialized form differs from Git. Confirm the field semantics before ignoring it.
Helm output is nondeterministic
Templates that generate random values or timestamps create a new desired manifest on each render. Move generated values into stable inputs or a separately managed Secret.
Two Applications manage one resource
Search Argo CD resource ownership and tracking labels. Multiple Applications targeting the same object create a permanent reconciliation fight.
Use ignore rules narrowly
Argo CD supports diff customization, but an ignore rule should name the specific resource and JSON pointer or managed-field manager. Avoid ignoring an entire spec, because genuine drift would disappear from review.
Before adding a rule, document:
- Which controller changes the field
- Why that controller is the intended owner
- Why the difference is operationally safe
- How actual configuration drift will still be detected
Avoid these responses
- Do not keep clicking Sync; repetition does not resolve competing ownership.
- Do not enable
selfHealuntil the diff is understood; it can create a write loop. - Do not edit the live object as the permanent fix. Correct the desired source or ownership model.
If the issue is recovery from a bad release, see Argo CD rollback should start from Git.