argoproj/argo-workflows · error

failed to parse certificate authority %q

Error message

failed to parse certificate authority %q

What it means

The CA file at caCert was read successfully, but its contents are not a valid PEM-encoded certificate, so AppendCertsFromPEM added nothing to the root pool. GetClientTLSConfig rejects the config rather than silently trusting no roots.

Source

Thrown at util/tls/tls.go:173

// Client certificate authentication requires both clientCert and clientKey. If caCert is provided,
// the certificate authority is used instead of the system roots to verify the server certificate.
// The insecureSkipVerify parameter controls whether the server's certificate is verified.
func GetClientTLSConfig(clientCert, clientKey, caCert string, insecureSkipVerify bool) (*tls.Config, error) {
	tlsConfig := &tls.Config{
		InsecureSkipVerify: insecureSkipVerify,
		MinVersion:         tls.VersionTLS12,
	}
	if (clientCert == "") != (clientKey == "") {
		return nil, fmt.Errorf("client certificate authentication requires both clientCert and clientKey")
	}
	if caCert != "" {
		caPEM, err := os.ReadFile(caCert)
		if err != nil {
			return nil, fmt.Errorf("failed to read certificate authority: %w", err)
		}
		certPool := x509.NewCertPool()
		if ok := certPool.AppendCertsFromPEM(caPEM); !ok {
			return nil, fmt.Errorf("failed to parse certificate authority %q", caCert)
		}
		tlsConfig.RootCAs = certPool
	}
	if clientCert != "" && clientKey != "" {
		cert, err := tls.LoadX509KeyPair(clientCert, clientKey)
		if err != nil {
			return nil, err
		}
		tlsConfig.Certificates = []tls.Certificate{cert}
	}
	return tlsConfig, nil
}

View on GitHub (pinned to 35bff19146)

Solutions

  1. Inspect the file: it must contain a '-----BEGIN CERTIFICATE-----' PEM block (openssl x509 -in ca.crt -text -noout)
  2. Re-download/export the CA in PEM format (for DER: openssl x509 -inform der -in ca.der -out ca.crt)
  3. Make sure the path points to the CA certificate, not the key or a stale error-page file
  4. Regenerate or re-fetch the Argo server CA from the correct secret/configmap

Example fix

# before (DER binary fails to parse)
ca.der
# after
openssl x509 -inform der -in ca.der -out ca.crt
# then pass ca.crt as the caCert argument
Defensive patterns

Strategy: validation

Validate before calling

func validCAPEM(path string) error {
    b, err := os.ReadFile(path)
    if err != nil { return err }
    if !bytes.Contains(b, []byte("-----BEGIN CERTIFICATE-----")) {
        return fmt.Errorf("%s is not PEM certificate data", path)
    }
    pool := x509.NewCertPool()
    if !pool.AppendCertsFromPEM(b) { return fmt.Errorf("%s: no parseable certs", path) }
    return nil
}

Try / catch

if err := validCAPEM(caCert); err != nil {
    return fmt.Errorf("invalid CA bundle: %w", err)
}
config, err := tls.GetClientTLSConfig(clientCert, clientKey, caCert, insecure)

Prevention

When it happens

Trigger: Calling GetClientTLSConfig with a caCert path whose file contains empty data, HTML (e.g. a proxy error page), a private key instead of a cert, a DER-encoded binary cert, or an otherwise malformed PEM block.

Common situations: Downloading the CA with curl through an auth-walled proxy and saving the HTML error page; pointing at the client key instead of the CA cert; using a DER/binary certificate without converting to PEM; truncated or concatenated wrong files.

Understand the failure class

Related errors


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