What Sync Failed means
Sync Failed is an operation result, not a comparison result. ArgoCD ran a
sync — it tried to apply the desired state to the cluster — and the apply itself
returned an error. Unlike OutOfSync, you cannot resolve this by just clicking
sync again; the underlying error has to be fixed first.
But before you assume the apply failed, rule out the step before it: ArgoCD can
only apply manifests it managed to generate. If the repo-server failed to
render the manifests, you get a ComparisonError and there is no apply at all.
The two failures live in different places and have different fixes:
ComparisonError→ repo-server could not produce the desired state. Detail is in.status.conditionsand the repo-server logs.- operation
Failed→ manifests rendered, the apply ran, the API server (or a hook, or a webhook) rejected something. Detail is in.status.operationState.
Diagnose it
argocd app get <app-name>
argocd app sync <app-name> --dry-run
Read the operation message and the per-resource status. The full detail is in the
Application resource — and check conditions to separate a comparison failure
from an apply failure:
# Apply-side detail
kubectl get application <app-name> -n argocd \
-o jsonpath='{.status.operationState.message}'
# Comparison-side detail (manifest generation)
kubectl get application <app-name> -n argocd \
-o jsonpath='{.status.conditions}'
kubectl get application <app-name> -n argocd -o yaml | less
# inspect .status.operationState, .status.resources[].message, .status.conditions
Typical apply errors that surface here:
# Immutable field
Deployment.apps "api" is invalid: spec.selector: field is immutable
# Missing CRD
unable to recognize "": no matches for kind "Rollout" in version "argoproj.io/v1alpha1"
# Admission webhook rejection
admission webhook "validate.kyverno.svc" denied the request: ...
# Failed PreSync hook
Job "db-migrate" failed: BackoffLimitExceeded
# Comparison failure (NOT an apply error — look in repo-server logs)
ComparisonError: Manifest generation error (cached): ...
If a hook failed, read the hook's Pod logs directly:
kubectl logs job/<hook-job> -n <namespace>
Caution
An immutable-field error (commonly spec.selector on a Deployment or
the clusterIP on a Service) cannot be fixed by syncing. The existing
resource must be deleted and recreated, or the manifest reverted to match the
live immutable value. Plan this carefully — deleting a Service drops its ClusterIP.
Causes, each diagnosed and fixed
1. Manifest generation failed (ComparisonError)
The repo-server clones your repo and runs Helm/Kustomize/your plugin to produce
manifests; a non-zero exit fails generation and the error is cached "to avoid
runaway retries," so a stale message can persist after you push a fix
(FAQ). A slow render fails with
Context deadline exceeded.
- Diagnose:
.status.conditionsshowsComparisonError. Search the repo-server logs for the app name:kubectl logs -n argocd deploy/argocd-repo-server | grep <app-name>. - Fix: correct the chart/overlay/values error and push. Then hard refresh
to clear the cached error (
argocd app get <app> --hard-refresh). For generation timeouts, raise--repo-server-timeout-secondsand scale up the repo-server (FAQ).
2. Immutable field rejected by the API server
A manifest changes a field Kubernetes forbids editing in place.
- Diagnose: per-resource message reads
field is immutable. - Fix: revert the manifest to the live value, or delete and recreate the
resource deliberately (see the warning above).
Replace=trueas a sync option useskubectl replace/createand can also recreate it (Sync Options).
3. Missing CRD
The custom resource is applied before (or without) its CustomResourceDefinition.
- Diagnose:
no matches for kind/the server could not find the requested resource. - Fix: install the CRD first. If the CRD ships in the same app, give it a
lower
argocd.argoproj.io/sync-waveso it applies first, or set theSkipDryRunOnMissingResource=truesync option so the dry-run does not fail on the unknown kind (Sync Options).
4. Admission / validation webhook denial
OPA Gatekeeper, Kyverno, or another ValidatingWebhookConfiguration rejects the
resource.
- Diagnose:
admission webhook "..." denied the request. - Fix: the message names the policy — bring the manifest into compliance, or
fix the policy. If the resource is a valid type the webhook mishandles, the
Validate=falsesync option skips kubectl validation (Sync Options).
5. PreSync / Sync / PostSync hook failed
Hooks run inside the sync operation. "If any PreSync fails, the entire sync stops"; a failed hook marks the whole operation Failed (Sync Phases and Waves).
- Diagnose: message names a
Job(e.g.db-migrate failed: BackoffLimitExceeded). Read its logs withkubectl logs job/<job>. - Fix: repair the underlying job (a broken migration, a missing secret), then
re-sync. A
SyncFailhook (argocd.argoproj.io/hook: SyncFail) can do cleanup when a sync fails.
6. Resource in a wave never goes Healthy (stalled phases)
ArgoCD applies waves in ascending order with a delay (default 2s,
ARGOCD_SYNC_WAVE_DELAY) and assesses health between them; PostSync runs only
"after Sync completes successfully and resources reach healthy status." If an
early wave's resource stays unhealthy, later waves never run and the operation
eventually fails or times out
(Sync Phases and Waves).
- Diagnose: the operation hangs in
Progressing; the failing wave's resource isDegraded/Progressinginargocd app get. Note that Ingress, StatefulSet and SealedSecret have known health-check quirks that read asProgressing(FAQ). - Fix: make the stuck resource healthy (or correct a wrong sync-wave order); add a custom health check for types ArgoCD assesses incorrectly.
7. Shared resource owned by another Application
Two Applications manage the same object.
- Diagnose:
SharedResourceWarning. With theFailOnSharedResource=truesync option, ArgoCD "will fail the sync whenever it finds a resource ... already applied in the cluster by another Application" (Sync Options). - Fix: make exactly one Application own the resource; remove it from the other's source.
8. RBAC on the target namespace
The application-controller ServiceAccount lacks permission on the target namespace.
- Diagnose:
forbidden: User "system:serviceaccount:argocd:..." cannot create/patch .... - Fix: grant the controller the needed Role/RoleBinding in the target namespace.
Fix it
- Run
argocd app get <app-name>. First check.status.conditions: a ComparisonError means manifests never rendered — fix it in the repo-server logs, not the cluster. - Otherwise read
.status.operationStateand the per-resource message, then classify: immutable field, missing CRD, webhook denial, hook failure, stalled wave, shared resource, or RBAC. - Apply the matching fix from the section above — each class has a different one.
- For a fixed ComparisonError, hard-refresh to clear the cached error before re-syncing.
- Re-run
argocd app sync <app-name>only after the root error is addressed. Note an automated sync "will not reattempt against the same commit" after failure, so push a new commit or sync manually (Automated Sync).
A spec.syncPolicy.retry block (limit, backoff.duration, backoff.factor,
backoff.maxDuration) retries transient apply failures with exponential backoff,
but it will not fix a real error — it only buys time for flaky dependencies
(Automated Sync).
How Intellira diagnoses this
Intellira reads the application's conditions and operationState from the
ArgoCD MCP server and first decides which side failed — manifest generation
(ComparisonError) or apply — instead of treating every red app the same. On the
apply side it identifies the failing resource and the class of error: immutable
field, missing CRD, webhook denial, stalled wave, shared resource, or RBAC. When a
PreSync hook is at fault, it follows the chain into the hook Job's logs via the
Kubernetes MCP server, so the answer is "the db-migrate PreSync Job exited
non-zero because the migration failed," not a generic "sync failed." That is the
difference between a status and a root cause.
Sources
- Sync Phases and Waves — Argo CD
- Sync Options — Argo CD
- Automated Sync Policy — Argo CD
- FAQ — Argo CD
By Intellira Engineering. AI-assisted draft, reviewed by the Intellira engineering team; claims cited inline; last verified 2026-06-02.