What OutOfSync means
In ArgoCD, sync status answers one question: does the live state in the
cluster match the target (desired) state declared in Git? Per the official docs,
"a deployed application whose live state deviates from the target state is
considered OutOfSync" (Argo CD overview).
ArgoCD "reports & visualizes the differences, while providing facilities to
automatically or manually sync the live state back to the desired target state"
(Argo CD overview).
This is independent of health status — an app can be Healthy and
OutOfSync at the same time. OutOfSync has several distinct causes, and they need
different fixes. Some are a missing field (drift), some are a missing resource
(prune or TTL), some are a field that ArgoCD will never win against (webhooks,
controllers, server-side defaults). Identify the mechanism before you sync.
Diagnose it
Start with the diff. It is the single most useful command here:
argocd app get <app-name>
argocd app get <app-name> --refresh # force a fresh comparison
argocd app diff <app-name>
===== apps/Deployment /payments/payments-api ======
< replicas: 3 # desired (Git)
> replicas: 5 # live (cluster)
Warning: Always run
argocd app diffbefore syncing. A blind sync overwrites live drift with Git — correct if the drift was an accidental manual edit, but destructive if someone is mid-incident and manually scaled up a deployment.
Then classify what the diff is telling you:
| What the diff shows | Likely mechanism | Jump to |
|---|---|---|
A field you set in Git differs (e.g. replicas, image) | Manual edit, or a controller owns that field | Drift |
Fields you never wrote (sidecars, injected labels/annotations, cpu/memory defaults) | Mutating webhook or server-side API defaults | Injected fields |
| Diff is empty but app still OutOfSync | A resource is pending prune, or a Job/Workflow was TTL-deleted | Missing resources |
| Extra resources generated by another tool | Extraneous resource / instance-label conflict | Extraneous |
| OutOfSync only during a deploy, clears on its own | Multi-wave sync in progress | Sync in progress |
To inspect field ownership (who last wrote each field), read managedFields:
kubectl get deployment payments-api -n payments -o yaml --show-managed-fields
1. Drift on a field you manage
A manual kubectl edit/kubectl scale, or a controller (HPA, VPA) that owns a
field, changed something ArgoCD also declares in Git. If it is a one-off manual
edit, decide direction and sync. If a controller re-mutates the field on every
apply, the app flaps back to OutOfSync.
Diagnose: argocd app diff shows a field you control. Check managedFields
(above) — if the manager is kube-controller-manager or an HPA, the controller
owns it, not a human.
Fix (manual edit): decide which side is correct.
# Git is correct (accidental edit): overwrite live
argocd app sync <app-name>
# Live is correct (deliberate, uncommitted change): commit it to Git first, then sync
Fix (controller owns the field): add an ignoreDifferences entry so ArgoCD
stops treating it as drift. ArgoCD lets you "optionally ignore differences of
problematic resources" using "RFC6902 JSON patches" (jsonPointers) and "JQ path
expressions" (jqPathExpressions)
(Diff Customization).
spec:
ignoreDifferences:
- group: apps
kind: Deployment
jsonPointers:
- /spec/replicas
Critical:
ignoreDifferencesby default only changes the diff — it does not change what gets applied. ArgoCD "uses theignoreDifferencesconfig just for computing the diff … However during the sync stage, the desired state is applied as-is" (Sync Options). So with auto-syncselfHeal: true, ArgoCD will still pushreplicas: 3and fight the HPA. To make sync respect the ignore rule, add theRespectIgnoreDifferences=truesync option — it works by "calculating and pre-patching the desired state before applying it in the cluster" (Sync Options).
spec:
syncPolicy:
syncOptions:
- RespectIgnoreDifferences=true
If you run automated sync with selfHeal: true, ArgoCD will reapply Git on its
own: "if the selfHeal flag is set to true, then the sync will be attempted again
after self-heal timeout (5 seconds by default)"
(Automated Sync Policy).
Pause auto-sync (or add the ignore + RespectIgnoreDifferences) before debugging a
flapping field, or self-heal will fight your manual changes.
2. Fields injected by webhooks or the API server
The diff shows fields you never wrote in Git: an injected sidecar container,
labels/annotations added by a policy controller, or resources.requests the API
server filled in as a default. A mutating admission webhook modifies resources
as they pass through the API server; client-side diff has no way to predict those
fields, so the app reports OutOfSync forever.
Diagnose: the diff adds fields that aren't in your manifest, and they reappear
after every sync. kubectl get ... --show-managed-fields shows a manager other
than ArgoCD (e.g. a webhook's service account or kube-apiserver).
Fix (preferred — server-side diff): ArgoCD's server-side diff "will execute a Server-Side Apply in dryrun mode for each resource" so "Kubernetes Admission Controllers will participate in the diff calculation" (Diff Strategies). Note: "Server-Side Diff does not include changes made by mutation webhooks by default" — for webhook-injected fields you must also opt in (Diff Strategies).
metadata:
annotations:
argocd.argoproj.io/compare-options: ServerSideDiff=true,IncludeMutationWebhook=true
IncludeMutationWebhook "is only effective when Server-Side Diff is enabled"
(Diff Strategies).
Fix (alternative — ignore by field manager): if you can't enable server-side
diff, ignore everything a given manager owns. managedFieldsManagers ignores
"differences from fields owned by specific managers defined in
metadata.managedFields in live resources"
(Diff Customization).
spec:
ignoreDifferences:
- group: ''
kind: Pod
managedFieldsManagers:
- my-mutating-webhook
As in section 1, pair this with
RespectIgnoreDifferences=true if you also need sync (not just the diff) to leave
the field alone.
3. Empty diff: pending prune or TTL-deleted resources
The app is OutOfSync but argocd app diff shows no field differences. The drift
is a missing or extra resource, not a changed field.
Pending prune. A resource was removed from Git, but pruning is disabled, so it still lives in the cluster: "The app will be out of sync if Argo CD expects a resource to be pruned" (Sync Options).
- Diagnose:
argocd app get <app-name>lists a resource withOutOfSyncand a prune/delete intent; the resource is absent from current Git. - Fix: either delete it intentionally with
argocd app sync <app-name> --prune, or, if you deliberately keep it, mark itPrune=falseand silence the status with theIgnoreExtraneouscompare option (see section 4).
TTL-deleted Jobs/Workflows. A Job with spec.ttlSecondsAfterFinished (or an
Argo Workflow ttlStrategy) is auto-deleted by the cluster after it completes.
Git still declares it, the cluster no longer has it → permanent OutOfSync.
- Diagnose: the OutOfSync resource is a completed
Job/Workflowthat no longer exists in the cluster, and its manifest sets a TTL. - Fix: drive cleanup through an ArgoCD resource hook with a delete policy
(
argocd.argoproj.io/hook-delete-policy: HookSucceeded) instead of a Kubernetes TTL, so ArgoCD — not the cluster — owns the deletion (Resource Hooks).
4. Extraneous or tool-generated resources
Another tool (Kustomize commonLabels, a generator, an operator) created
resources or labels ArgoCD did not, and they show up as drift. A classic case is a
label conflict: a tool adds app.kubernetes.io/instance, which ArgoCD also uses
for tracking.
Diagnose: the OutOfSync resources are ones your tooling generates, or the diff
is on the tracking label. argocd app get flags them as extra/OutOfSync.
Fix (exclude from sync status): annotate the resource so it no longer affects
overall status. IgnoreExtraneous lets you "exclude resources from the app's
overall sync status … if they are generated by a tool" — but "this only affects
the sync status. If the resource's health is degraded, then the app will also be
degraded"
(Compare Options).
metadata:
annotations:
argocd.argoproj.io/compare-options: IgnoreExtraneous
Fix (label conflict): change the tracking label key. Set
application.instanceLabelKey in argocd-cm; the docs recommend
argocd.argoproj.io/instance. Note "when you make this change your applications
will become out of sync and will need re-syncing"
(Argo CD FAQ).
5. Transient OutOfSync during a multi-wave sync
If the app uses sync waves, it is normally OutOfSync while the sync runs and
clears once all waves complete. Sync waves are set with the
argocd.argoproj.io/sync-wave annotation; ArgoCD applies lower wave numbers first
and "there is currently a delay between each sync wave in order to give other
controllers a chance to react"
(Sync Phases and Waves).
Diagnose: OutOfSync only appears during a deploy and resolves itself. Check
argocd app get — an early-wave resource may be stuck Unhealthy.
Fix: usually none needed — wait for the sync to finish. But "because an application can have resources that are unhealthy in the first wave, it may be that the app can never get to healthy" (Sync Phases and Waves), which stalls all later waves. If the app is stuck, find the unhealthy early-wave resource and fix that — the OutOfSync status downstream is a symptom, not the cause.
How Intellira diagnoses this
Intellira fetches the application's sync status and the field-level diff through
the ArgoCD MCP server, then correlates each drifted item with its likely
mechanism — a recent kubectl change, an HPA that owns replicas, a
webhook-injected field, a resource pending prune, or a wave still in progress.
Instead of just reporting "OutOfSync," it points at which resource or field
drifted and whether a sync is safe or would overwrite an intentional live change.
Sources
- Argo CD — Declarative GitOps CD for Kubernetes (overview, OutOfSync definition)
- Argo CD — Diff Customization (ignoreDifferences, jsonPointers, jqPathExpressions, managedFieldsManagers)
- Argo CD — Diff Strategies (server-side diff, IncludeMutationWebhook, admission controllers in diff)
- Argo CD — Sync Options (RespectIgnoreDifferences, Prune behavior, ignoreDifferences applies as-is during sync)
- Argo CD — Compare Options (IgnoreExtraneous)
- Argo CD — Automated Sync Policy (auto-sync only when OutOfSync, selfHeal timeout)
- Argo CD — Sync Phases and Waves (sync-wave annotation, delay between waves, unhealthy early wave stalls sync)
- Argo CD — Resource Hooks (hook-delete-policy for Job cleanup instead of TTL)
- Argo CD — FAQ (instanceLabelKey / app.kubernetes.io/instance conflict)
By Intellira Engineering. AI-assisted draft, reviewed by the Intellira engineering team; claims cited inline; last verified 2026-06-02.