argoproj/argo-workflows · error

--client-certificate and --client-key must be provided toget

Error message

--client-certificate and --client-key must be provided together

What it means

NewAPIClient validates kubectl-style auth overrides before dialing the argo server. mTLS requires both a client certificate and its matching private key; supplying only one is guaranteed misconfiguration, so it fails fast with this error.

Source

Thrown at cmd/argo/commands/client/conn.go:66

	cmd.PersistentFlags().StringVar(&instanceID, "instanceid", os.Getenv("ARGO_INSTANCEID"), "submit with a specific controller's instance id label. Default to the ARGO_INSTANCEID environment variable.")
	// "-s" like kubectl
	cmd.PersistentFlags().StringVarP(&ArgoServerOpts.URL, "argo-server", "s", os.Getenv("ARGO_SERVER"), "API server `host:port`. e.g. localhost:2746. Defaults to the ARGO_SERVER environment variable.")
	cmd.PersistentFlags().StringVar(&ArgoServerOpts.Path, "argo-base-href", os.Getenv("ARGO_BASE_HREF"), "Path to use with HTTP client due to Base HREF. Defaults to the ARGO_BASE_HREF environment variable.")
	cmd.PersistentFlags().BoolVar(&ArgoServerOpts.HTTP1, "argo-http1", os.Getenv("ARGO_HTTP1") == "true", "If true, use the HTTP client. Defaults to the ARGO_HTTP1 environment variable.")
	cmd.PersistentFlags().StringSliceVarP(&ArgoServerOpts.Headers, "header", "H", []string{}, "Sets additional header to all requests made by Argo CLI. (Can be repeated multiple times to add multiple headers, also supports comma separated headers) Used only when either ARGO_HTTP1 or --argo-http1 is set to true.")
	// "-e" for encrypted - like zip
	cmd.PersistentFlags().BoolVarP(&ArgoServerOpts.Secure, "secure", "e", os.Getenv("ARGO_SECURE") != "false", "Whether or not the server is using TLS with the Argo Server. Defaults to the ARGO_SECURE environment variable.")
	// "-k" like curl
	cmd.PersistentFlags().BoolVarP(&ArgoServerOpts.InsecureSkipVerify, "insecure-skip-verify", "k", os.Getenv("ARGO_INSECURE_SKIP_VERIFY") == "true", "If true, the Argo Server's certificate will not be checked for validity. This will make your HTTPS connections insecure. Defaults to the ARGO_INSECURE_SKIP_VERIFY environment variable.")
}

func NewAPIClient(ctx context.Context) (context.Context, apiclient.Client, error) {
	// Reuse the explicit kubectl client certificate flags in server mode.
	ArgoServerOpts.ClientCert = overrides.AuthInfo.ClientCertificate
	ArgoServerOpts.ClientKey = overrides.AuthInfo.ClientKey
	ArgoServerOpts.CACert = overrides.ClusterInfo.CertificateAuthority
	if (ArgoServerOpts.ClientCert == "") != (ArgoServerOpts.ClientKey == "") {
		return nil, nil, errors.New("--client-certificate and --client-key must be provided together")
	}

	var proxy func(*http.Request) (*url.URL, error)
	if overrides.ClusterInfo.ProxyURL != "" {
		proxyURL, err := url.Parse(overrides.ClusterInfo.ProxyURL)
		if err != nil {
			return nil, nil, err
		}
		proxy = http.ProxyURL(proxyURL)
	}
	return apiclient.NewClientFromOptsWithContext(ctx,
		apiclient.Opts{
			ArgoServerOpts: ArgoServerOpts,
			InstanceID:     instanceID,
			AuthSupplier: func() string {
				authString, err := GetAuthString(ctx)
				if err != nil {
					logger := logging.RequireLoggerFromContext(ctx)

View on GitHub (pinned to 35bff19146)

Solutions

  1. Pass both flags together: --client-certificate /path/tls.crt --client-key /path/tls.key.
  2. Fix the kubeconfig user entry so client-certificate-data and client-key-data are both present.
  3. If the server doesn't require client certs, remove both flags and authenticate another way (token, SSO).

Example fix

// before
argo list --client-certificate tls.crt
// after
argo list --client-certificate tls.crt --client-key tls.key
Defensive patterns

Strategy: validation

Validate before calling

if [ -n "$CLIENT_CERT" ] || [ -n "$CLIENT_KEY" ]; then
  [ -n "$CLIENT_CERT" ] && [ -n "$CLIENT_KEY" ] || { echo 'need both cert and key'; exit 1; }
fi

Try / catch

if ! argo list --client-certificate "$c" --client-key "$k" 2>err.txt; then
  grep -q 'must be provided together' err.txt && echo 'fix mTLS flags'
fi

Prevention

When it happens

Trigger: Setting --client-certificate without --client-key (or vice versa) on any argo CLI command, or having only one of client-certificate-data/client-key-data in the kubeconfig user entry.

Common situations: Copying kubectl config examples that only set the cert; rotating certificates and replacing only one file; shell scripts where one flag is conditionally added.

Understand the failure class

Related errors


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/49167b3f26ac3e49. Report an issue: GitHub.