Checklist
Describe the bug
In --core (headless) mode, the argocd CLI boots an in-process API server via cmd/argocd/commands/headless/headless.go. Starting from v3.0.0, ArgoCDServerOpts has a new field SyncWithReplaceAllowed (introduced by #20720 / #21427 to gate sync --replace on the server level). However, headless.go never sets this field when constructing the in-process server, so it is left at the Go zero value (false).
As a result, any argocd --core app sync --replace ... invocation on a v3.x CLI (against any cluster) fails with:
FailedPrecondition: sync with replace was disabled on the API Server level via the server configuration
The cluster's argocd-cmd-params-cm / server env vars / server args are all irrelevant in --core mode because the CLI isn't using the remote argocd-server at all — it uses its own in-process one.
This is inconsistent with:
- The default of the standalone
argocd-server binary, which defaults syncWithReplaceAllowed to true (see cmd/argocd-server/commands/argocd_server.go:331).
- The expectation that
--core is a drop-in for the server gRPC API for CLI usage.
To Reproduce
With any v3.x CLI (v3.0.0 through v3.2.x, verified):
# Login to any cluster via kubeconfig, any argocd install (or none — the flag is independent).
# Create any Application CR, then:
argocd --core app sync --replace <app-name>
Result:
FATA[0000] rpc error: code = FailedPrecondition desc = sync with replace was disabled on the API Server level via the server configuration
Setting ARGOCD_SYNC_WITH_REPLACE_ALLOWED=true in the shell environment does not help, because headless.go does not read any env var when it constructs ArgoCDServerOpts.
Setting server.sync.replace.allowed: "true" in the cluster's argocd-cmd-params-cm does not help either, because --core does not connect to the cluster's argocd-server.
Expected behavior
argocd --core app sync --replace should succeed (or at least respect the same default as the standalone server, which is "allowed"), unless the user has explicitly opted into disabling replace.
Actual behavior
argocd --core app sync --replace always fails with FailedPrecondition on any v3.x CLI.
Source references
Confirmed the same code path in master (verified on April/2026): headless.go still does not set the field.
Version
argocd: v3.1.8+... (any v3.x)
argocd-server: irrelevant (`--core` bypasses the remote server)
Kubernetes: any
Logs
{"level":"fatal","msg":"rpc error: code = FailedPrecondition desc = sync with replace was disabled on the API Server level via the server configuration","time":"2026-04-23T18:21:14Z"}
Suggested fix
Mirror the standalone server's flag default when constructing the in-process server:
--- a/cmd/argocd/commands/headless/headless.go
+++ b/cmd/argocd/commands/headless/headless.go
@@ -274,6 +274,7 @@ func MaybeStartLocalServer(...) (...) {
srv := server.NewServer(ctx, server.ArgoCDServerOpts{
EnableGZip: false,
Namespace: namespace,
ListenPort: *port,
AppClientset: appClientset,
DisableAuth: true,
RedisClient: redis.NewClient(redisOptions),
Cache: servercache.NewCache(appstateCache, 0, 0),
KubeClientset: kubeClientset,
DynamicClientset: dynamicClientset,
KubeControllerClientset: controllerClientset,
Insecure: true,
ListenHost: *address,
RepoClientset: &forwardRepoClientset{...},
EnableProxyExtension: false,
+ SyncWithReplaceAllowed: env.ParseBoolFromEnv("ARGOCD_SYNC_WITH_REPLACE_ALLOWED", true),
}, server.ApplicationSetOpts{})
That makes the --core behavior match the standalone server:
- Default:
true (allowed), matching cmd/argocd-server/commands/argocd_server.go:331.
- Users who want to disable replace for headless usage can set
ARGOCD_SYNC_WITH_REPLACE_ALLOWED=false in the shell.
Happy to send a PR if this repro is acceptable.
Workaround
Use argocd CLI v2.x (the SyncWithReplaceAllowed field and the server-side gate do not exist pre-v3.0.0). This is obviously not a long-term fix — v2.x CLI against a v3.x server is outside the supported skew window.
Checklist
argocd version.Describe the bug
In
--core(headless) mode, the argocd CLI boots an in-process API server viacmd/argocd/commands/headless/headless.go. Starting from v3.0.0,ArgoCDServerOptshas a new fieldSyncWithReplaceAllowed(introduced by #20720 / #21427 to gatesync --replaceon the server level). However,headless.gonever sets this field when constructing the in-process server, so it is left at the Go zero value (false).As a result, any
argocd --core app sync --replace ...invocation on a v3.x CLI (against any cluster) fails with:The cluster's
argocd-cmd-params-cm/ server env vars / server args are all irrelevant in--coremode because the CLI isn't using the remote argocd-server at all — it uses its own in-process one.This is inconsistent with:
argocd-serverbinary, which defaultssyncWithReplaceAllowedtotrue(seecmd/argocd-server/commands/argocd_server.go:331).--coreis a drop-in for the server gRPC API for CLI usage.To Reproduce
With any v3.x CLI (v3.0.0 through v3.2.x, verified):
Result:
Setting
ARGOCD_SYNC_WITH_REPLACE_ALLOWED=truein the shell environment does not help, becauseheadless.godoes not read any env var when it constructsArgoCDServerOpts.Setting
server.sync.replace.allowed: "true"in the cluster'sargocd-cmd-params-cmdoes not help either, because--coredoes not connect to the cluster's argocd-server.Expected behavior
argocd --core app sync --replaceshould succeed (or at least respect the same default as the standalone server, which is "allowed"), unless the user has explicitly opted into disabling replace.Actual behavior
argocd --core app sync --replacealways fails withFailedPreconditionon any v3.x CLI.Source references
ArgoCDServerOptsbuilt withoutSyncWithReplaceAllowed.ArgoCDServerOptsstruct (v3.1.8): https://github.com/argoproj/argo-cd/blob/v3.1.8/server/server.go#L241 —SyncWithReplaceAllowed bool.true(v3.1.8): https://github.com/argoproj/argo-cd/blob/v3.1.8/cmd/argocd-server/commands/argocd_server.go#L331Confirmed the same code path in
master(verified on April/2026):headless.gostill does not set the field.Version
Logs
Suggested fix
Mirror the standalone server's flag default when constructing the in-process server:
That makes the
--corebehavior match the standalone server:true(allowed), matchingcmd/argocd-server/commands/argocd_server.go:331.ARGOCD_SYNC_WITH_REPLACE_ALLOWED=falsein the shell.Happy to send a PR if this repro is acceptable.
Workaround
Use
argocdCLI v2.x (theSyncWithReplaceAllowedfield and the server-side gate do not exist pre-v3.0.0). This is obviously not a long-term fix — v2.x CLI against a v3.x server is outside the supported skew window.