🎉 DevOps Interview Prep Bundle is live — 1000+ Q&A across 20 topicsGet it →
All Articles

ArgoCD Sync Failed: Unknown Field and Validation Errors — Fix

ArgoCD sync failing with 'unknown field', 'strict decoding error', or 'field is immutable'? Here are the exact causes and kubectl/ArgoCD commands to fix each one without recreating resources.

Shubham4 min read
Share:Tweet

ArgoCD sync failures with validation errors are frustrating because the YAML looks fine locally but ArgoCD rejects it. Here are the most common causes and how to fix each.

Error 1: "unknown field" / Strict Decoding Error

error: error validating data: ValidationError(Deployment.spec.template.spec.containers[0]):
unknown field "securityContext.readOnlyRootFilesystem" in io.k8s.api.core.v1.Container

Or the newer version:

error: strict decoding error: unknown field "spec.template.spec.containers[0].unknownField"

Cause: The field exists in your YAML but does not exist in the Kubernetes API version you are targeting, or there is a typo.

Fix:

bash
# Check what API version your cluster supports for this resource
kubectl explain deployment.spec.template.spec.containers --recursive | grep securityContext
 
# Validate your manifest against the cluster API before applying
kubectl apply --dry-run=server -f deployment.yaml
 
# If using ArgoCD CLI, check what ArgoCD is actually sending
argocd app manifests <app-name> | kubectl apply --dry-run=server -f -

Common typos that cause this:

  • readinessProbe spelled as readyProbe
  • securityContext at wrong level (pod vs container)
  • resources.limits vs resources.limit

Error 2: "field is immutable"

The Deployment "myapp" is invalid: spec.selector: Invalid value: v1.LabelSelector{...}: field is immutable

Cause: You changed a label selector in a Deployment/StatefulSet, which cannot be changed after creation.

Fix: Delete and recreate the resource. ArgoCD cannot patch immutable fields.

bash
# Option 1: Let ArgoCD handle it with replace
# In ArgoCD UI: App → Sync → Force
 
# Option 2: Manual delete + sync
kubectl delete deployment myapp -n production
argocd app sync <app-name>
 
# Option 3: Use ArgoCD sync with Replace strategy
# In your Application spec:
yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
spec:
  syncPolicy:
    syncOptions:
    - Replace=true   # Uses kubectl replace instead of apply

Warning: Replace=true deletes and recreates resources. Use with caution on StatefulSets.

Error 3: "resource conflict" / Apply Failed

error: Apply failed with 1 conflict: conflict with "kubectl-client-side-apply":
.spec.replicas

Cause: Someone used kubectl apply directly on the cluster, creating a field manager conflict with ArgoCD's server-side apply.

Fix:

bash
# Clear the conflicting field manager by forcing the sync
argocd app sync <app-name> --force
 
# Or manually remove the conflicting annotation
kubectl annotate deployment myapp kubectl.kubernetes.io/last-applied-configuration- -n production
 
# Permanent fix: enable server-side apply in ArgoCD

In ArgoCD Application:

yaml
spec:
  syncPolicy:
    syncOptions:
    - ServerSideApply=true

Server-side apply is the correct long-term approach — it handles conflicts gracefully.

Error 4: "resource not found" During Sync

Sync operation to 1.2.3 failed: error creating Deployment/myapp: namespaces "production" not found

Cause: The namespace does not exist and CreateNamespace=true is not set.

Fix:

yaml
spec:
  syncPolicy:
    syncOptions:
    - CreateNamespace=true

Or create it manually:

bash
kubectl create namespace production
argocd app sync <app-name>

Error 5: Hook Errors Blocking Sync

one or more synchronization tasks are not valid:
* invalid hook annotation: PostSync

Cause: Malformed hook annotation on a Job or other resource.

Diagnose:

bash
argocd app sync <app-name> --dry-run
# Shows all resources and their hook status

Fix — correct hook annotation syntax:

yaml
metadata:
  annotations:
    argocd.argoproj.io/hook: PostSync           # not "post-sync" or "postsync"
    argocd.argoproj.io/hook-delete-policy: HookSucceeded

Valid hook values: PreSync, Sync, PostSync, SyncFail

Error 6: CRD Not Found

error: unable to recognize "STDIN": no matches for kind "ServiceMonitor" in version "monitoring.coreos.com/v1"

Cause: The CRD for this resource is not installed in the cluster.

Fix:

bash
# Check if CRD exists
kubectl get crd | grep servicemonitor
 
# If missing, install it first — example for Prometheus CRDs
kubectl apply -f https://raw.githubusercontent.com/prometheus-operator/prometheus-operator/main/bundle.yaml
 
# Then sync
argocd app sync <app-name>

For apps that depend on CRDs from other apps, use ArgoCD sync waves:

yaml
metadata:
  annotations:
    argocd.argoproj.io/sync-wave: "1"   # Lower number = syncs first

Quick Diagnostic Commands

bash
# Full sync status with error details
argocd app get <app-name> --show-operation
 
# See what ArgoCD would apply
argocd app manifests <app-name>
 
# Diff between desired and live state
argocd app diff <app-name>
 
# Force resync from Git
argocd app sync <app-name> --force --prune
 
# Check ArgoCD server logs for deeper errors
kubectl logs -n argocd -l app.kubernetes.io/name=argocd-server --tail=50

Most ArgoCD sync errors are either field typos, immutable field changes, or missing prerequisites (CRDs, namespaces). The --dry-run=server approach catches most issues before they block your pipeline.


More ArgoCD fixes? Read our ArgoCD app stuck OutOfSync fix and ArgoCD RBAC permission denied fix.

🔧

Today I Fixed

Short real fixes from production — posted daily

Browse fixes
Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Comments