Pre-sync hook Job runs twice when sync retries after transient API server error
0 reputation · 28 Mar 2026, 06:08 UTC
Symptom
An ArgoCD Application configured with a pre-sync hook (Job) executes the hook twice when a sync attempt encounters a transient API server error and automatically retries. The first sync attempt creates the hook Job and begins applying manifests; a brief API server outage interrupts the apply. ArgoCD's retry logic re-initiates the sync from the start, creating a second hook Job with the same name before the first Job completes or is cleaned up.
Context
ArgoCD v2.9+ uses server-side apply (SSA) with field manager argocd for sync operations. The application controller implements exponential backoff for retries (configurable via application.controller.sync.retry.backoff.*), but does not track which hook resources have already been created during a prior attempt. Hook annotations lack built-in idempotency keys, and deletePolicy: HookSucceeded only removes the Job after successful completion — not before a retry spawns a duplicate.
Constraints
- Hook logic must remain idempotent externally (e.g., writing to a ConfigMap with a timestamp breaks if run twice).
- Disabling retries is not acceptable; transient errors must be handled automatically.
- SSA
Replace: truecannot be used because it would overwrite concurrent changes from other controllers.
What configuration or pattern ensures a pre-sync hook Job runs exactly once per successful sync, even when the sync is retried after a transient failure? Can the retry mechanism be made aware of already-created hook resources? Is there a supported way to gate hook creation on a sync-attempt identifier?