# How to Troubleshoot Argo CD Sync Failures: A Complete Guide

> Troubleshoot Argo CD sync failures by exploring sync controller issues, window policies, permissions, shared conflicts, and sync options. Fix your deployments now.

- Repository: [Argo Project/argo-cd](https://github.com/argoproj/argo-cd)
- Tags: how-to-guide
- Published: 2026-07-09

---

**Argo CD sync failures typically originate from five control-plane layers: the sync controller execution, sync-window policies, resource-permission validations, shared-resource conflicts, and misconfigured sync options.**

When an `Application` resource fails to reach the *Synced* state in the `argoproj/argo-cd` repository, the failure propagates through a specific chain of validation checks within the application controller. Understanding the exact execution flow in [`controller/sync.go`](https://github.com/argoproj/argo-cd/blob/main/controller/sync.go) allows you to diagnose whether the issue stems from authentication, policy restrictions, or resource conflicts.

## Understanding the Sync Controller Execution Flow

Every sync operation begins in [`controller/sync.go`](https://github.com/argoproj/argo-cd/blob/main/controller/sync.go), where the application controller generates a unique operation ID and initializes a `SyncContext`.

### Sync Context Generation and Error Handling

When a sync is triggered, the controller performs the following sequence:

1. Generates a unique **sync-ID** using `syncid.Generate()` for log correlation
2. Builds a `SyncContext` via the gitops-engine at `gitops-engine/pkg/sync.NewSyncContext`
3. Executes the actual apply/prune actions against the target cluster

If any step returns an error, the controller immediately sets `OperationState` to `OperationError` and propagates the message to the UI and CLI.

```go
// controller/sync.go
syncId, err := syncid.Generate()
…
syncCtx, cleanup, err := sync.NewSyncContext(
    compareResult.syncStatus.Revision,
    reconciliationResult,
    restConfig,
    rawConfig,
    m.kubectl,
    app.Spec.Destination.Namespace,
    opts...,
)

```

**Key diagnostic step:** Always retrieve the full operation state using `argocd app get <app> -o yaml` to inspect the `status.operationState.message` field associated with the `syncId`.

## Sync Window Policy Validation

Before any resource comparison occurs, the controller validates whether the current time falls within an active **sync window** defined in the `AppProject`.

### How Sync Windows Block Operations

The `syncWindowPreventsSync()` function evaluates the application's project-specific windows:

```go
// controller/sync.go
func syncWindowPreventsSync(app *v1alpha1.Application, proj *v1alpha1.AppProject) (bool, error) {
    window := proj.Spec.SyncWindows.Matches(app)
    …
    canSync, err := window.CanSync(isManual, operationStartTime)
    …
    return !canSync, nil
}

```

- **Manual syncs** only bypass windows if the specific window configuration permits manual actions
- Malformed window definitions return errors that block the sync entirely

Verify current window restrictions by running `argocd proj get <project>` and examining the `syncWindows` section.

## Resource Permission and Destination Checks

Each resource undergoes validation against the project's **allow/deny lists** and the destination cluster's namespace policy through `validateSyncPermissions()`.

### Validating Against Project Allowlists

The controller checks every resource against the `AppProject` constraints:

```go
// controller/sync.go
func validateSyncPermissions(project *v1alpha1.AppProject, destCluster *v1alpha1.Cluster,
    getProjectClusters func(string) ([]*v1alpha1.Cluster, error), un *unstructured.Unstructured,
    res *metav1.APIResource) error {
    …
}

```

**Permission failures** generate errors like *"resource X is not permitted in project Y"*. To resolve these, verify that the resource's group, kind, and target namespace appear in the project's allowlist using `argocd proj allowlist <project>`.

## Shared Resource Detection and Conflicts

Argo CD detects when multiple `Application` resources manage the same Kubernetes object. By default, the controller issues a warning, but you can configure it to fail the sync explicitly.

When `FailOnSharedResource=true` is set in the sync options, the controller executes this blocking logic:

```go
// controller/sync.go
hasSharedResource, sharedResourceMessage := hasSharedResourceCondition(app)
if syncOp.SyncOptions.HasOption("FailOnSharedResource=true") && hasSharedResource {
    state.Phase = common.OperationFailed
    state.Message = "Shared resource found: " + sharedResourceMessage
    return
}

```

Check for shared resource conditions in the application status: `argocd app get <app> -o yaml | grep -A5 "conditions"`.

## Sync Options That Affect Failure Modes

Many sync failures stem from configuration options that modify how the controller applies resources. These options reside in `spec.syncPolicy.syncOptions` or as the `argocd.argoproj.io/sync-options` annotation.

| Option | Effect | Failure Mode |
|--------|--------|--------------|
| `Prune=false` | Skips resource deletion | Orphaned resources remain when they should be removed |
| `FailOnSharedResource=true` | Fails on ownership conflicts | Prevents overwriting resources managed by other apps |
| `RespectIgnoreDifferences=true` | Applies ignoreDifferences during apply | May mask configuration drift |
| `ServerSideApply=true` | Uses `kubectl apply --server-side` | Can fail on field ownership conflicts with server-side apply |
| `CreateNamespace=true` | Auto-creates destination namespaces | Sync fails if namespace creation is forbidden |

Reference the full specification in [[`docs/user-guide/sync-options.md`](https://github.com/argoproj/argo-cd/blob/main/docs/user-guide/sync-options.md)](https://github.com/argoproj/argo-cd/blob/master/docs/user-guide/sync-options.md).

## Common Failure Signatures and Diagnostic Steps

Map symptoms to specific code paths using this diagnostic table:

| Symptom | Likely Cause | Verification Command |
|---------|--------------|---------------------|
| *OperationError: "Failed to get destination cluster"* | Cluster cache missing or authentication failure | `argocd app get <app> -o yaml` (check `operationState`) |
| *Sync blocked by sync window* | Current time outside allowed window | `argocd proj get <proj>` (review `syncWindows`) |
| *Resource X is not permitted* | Project denylist blocking group/kind | `argocd proj get <proj>` (check `spec` allow/deny) |
| *Shared resource found* | Ownership conflict with another app | `argocd app get <app> -o yaml` (check `conditions`) |
| *Validation error* | Resource cannot be client-side validated | Add `Validate=false` to sync options |

## Step-by-Step Debugging Workflow

Follow this systematic approach to isolate the failure layer:

1. **Inspect the application operation state**

   ```bash
   argocd app get <app> --output yaml
   ```

   Examine `status.operationState.phase` and `status.operationState.message` for the specific error returned by [`controller/sync.go`](https://github.com/argoproj/argo-cd/blob/main/controller/sync.go).

2. **Correlate with controller logs**

   ```bash
   kubectl logs -n argocd -l app.kubernetes.io/name=argocd-application-controller
   ```

   Filter by the `syncId` from step 1 to find the exact execution trace.

3. **Validate sync-window constraints**

   ```bash
   argocd proj get <project> -o yaml
   ```

   Confirm the `syncWindows` block permits the current operation type (manual vs automated).

4. **Test permission configurations**

   ```bash
   argocd proj allowlist <project>
   ```

   Ensure the target namespace and resource types are explicitly permitted.

5. **Execute a dry-run to isolate manifest errors**

   ```bash
   argocd app sync <app> --dry-run
   ```

   If dry-run succeeds but live sync fails, investigate `Prune`, `ServerSideApply`, or `resource.customizations` settings.

6. **Adjust sync options to resolve the specific failure**

   ```bash
   argocd app set <app> --sync-option Prune=false
   argocd app set <app> --sync-option FailOnSharedResource=true
   ```

## Summary

- **Sync failures** originate in [`controller/sync.go`](https://github.com/argoproj/argo-cd/blob/main/controller/sync.go) during `SyncContext` initialization, permission validation, or window checking.
- **Sync windows** defined in `AppProject` resources can block both automated and manual syncs unless explicitly configured to allow them.
- **Permission errors** occur when `validateSyncPermissions()` detects resources outside the project's allow/deny lists or unauthorized destination namespaces.
- **Shared resources** trigger failures when `FailOnSharedResource=true` is set and another `Application` already owns the object.
- **Diagnostic commands** include `argocd app get` for operation state, `argocd proj get` for policy validation, and `kubectl logs` for controller-level debugging.

## Frequently Asked Questions

### What does "Shared resource found" error mean in Argo CD?

This error occurs when the `FailOnSharedResource=true` sync option is enabled and the controller detects that another `Application` resource already manages the same Kubernetes object. The controller sets `state.Phase = common.OperationFailed` in [`controller/sync.go`](https://github.com/argoproj/argo-cd/blob/main/controller/sync.go) and prevents the sync to avoid configuration drift. Resolve this by removing the duplicate resource definition from one application or disabling the strict ownership check if the shared management is intentional.

### How do I bypass sync windows for manual operations?

Sync windows in `AppProject` specifications can restrict automated syncs to specific time ranges, but manual syncs require explicit window configuration to permit manual actions. The `syncWindowPreventsSync()` function checks `window.CanSync(isManual, operationStartTime)` where `isManual` indicates a user-triggered operation. If the window does not allow manual syncs, you must either wait for an active window or modify the `AppProject` to include `manualSync: true` in the window definition.

### Why does my sync fail with "resource X is not permitted in project Y"?

This error originates from `validateSyncPermissions()` in [`controller/sync.go`](https://github.com/argoproj/argo-cd/blob/main/controller/sync.go) when a resource's group, kind, or target namespace violates the project's allow/deny lists. The controller validates every resource against the `AppProject` specification before applying it. Fix this by updating the project's allowlist using `argocd proj allowlist <project>` to include the resource's API group and the destination namespace, or by moving the resource to a permitted namespace.

### How can I enable debug logging for sync operations?

To capture detailed `syncId`-prefixed logs from the sync controller, patch the `argocd-application-controller` deployment to set `ARGOCD_LOG_LEVEL=debug`. After applying the environment variable, trigger a sync and watch the logs with `kubectl logs`. The debug output includes the full `SyncContext` initialization sequence and detailed permission check results from [`controller/sync.go`](https://github.com/argoproj/argo-cd/blob/main/controller/sync.go), allowing you to trace exactly where the operation fails.