Skip to content

argocd --core app sync --replace always fails with sync with replace was disabled on the API Server level via the server configuration in v3.x #27529

@AdrianoAPaterlini

Description

@AdrianoAPaterlini

Checklist

  • I've searched in the docs and FAQ for my answer: https://bit.ly/argocd-faq
  • I've included steps to reproduce the bug.
  • I've pasted the output of argocd version.

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:

  1. The default of the standalone argocd-server binary, which defaults syncWithReplaceAllowed to true (see cmd/argocd-server/commands/argocd_server.go:331).
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtriage/pendingThis issue needs further triage to be correctly classified

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions