{"record":{"id":"d2cd62164236de2a","repo":"argoproj/argo-workflows","slug":"failed-to-parse-certificate-authority-q","errorCode":null,"errorMessage":"failed to parse certificate authority %q","messagePattern":"failed to parse certificate authority %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/tls/tls.go","lineNumber":173,"sourceCode":"// Client certificate authentication requires both clientCert and clientKey. If caCert is provided,\n// the certificate authority is used instead of the system roots to verify the server certificate.\n// The insecureSkipVerify parameter controls whether the server's certificate is verified.\nfunc GetClientTLSConfig(clientCert, clientKey, caCert string, insecureSkipVerify bool) (*tls.Config, error) {\n\ttlsConfig := &tls.Config{\n\t\tInsecureSkipVerify: insecureSkipVerify,\n\t\tMinVersion:         tls.VersionTLS12,\n\t}\n\tif (clientCert == \"\") != (clientKey == \"\") {\n\t\treturn nil, fmt.Errorf(\"client certificate authentication requires both clientCert and clientKey\")\n\t}\n\tif caCert != \"\" {\n\t\tcaPEM, err := os.ReadFile(caCert)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to read certificate authority: %w\", err)\n\t\t}\n\t\tcertPool := x509.NewCertPool()\n\t\tif ok := certPool.AppendCertsFromPEM(caPEM); !ok {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse certificate authority %q\", caCert)\n\t\t}\n\t\ttlsConfig.RootCAs = certPool\n\t}\n\tif clientCert != \"\" && clientKey != \"\" {\n\t\tcert, err := tls.LoadX509KeyPair(clientCert, clientKey)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\ttlsConfig.Certificates = []tls.Certificate{cert}\n\t}\n\treturn tlsConfig, nil\n}\n","sourceCodeStart":155,"sourceCodeEnd":186,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/util/tls/tls.go#L155-L186","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the file: it must contain a '-----BEGIN CERTIFICATE-----' PEM block (openssl x509 -in ca.crt -text -noout)","Re-download/export the CA in PEM format (for DER: openssl x509 -inform der -in ca.der -out ca.crt)","Make sure the path points to the CA certificate, not the key or a stale error-page file","Regenerate or re-fetch the Argo server CA from the correct secret/configmap"],"exampleFix":"# before (DER binary fails to parse)\nca.der\n# after\nopenssl x509 -inform der -in ca.der -out ca.crt\n# then pass ca.crt as the caCert argument","handlingStrategy":"validation","validationCode":"func validCAPEM(path string) error {\n    b, err := os.ReadFile(path)\n    if err != nil { return err }\n    if !bytes.Contains(b, []byte(\"-----BEGIN CERTIFICATE-----\")) {\n        return fmt.Errorf(\"%s is not PEM certificate data\", path)\n    }\n    pool := x509.NewCertPool()\n    if !pool.AppendCertsFromPEM(b) { return fmt.Errorf(\"%s: no parseable certs\", path) }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := validCAPEM(caCert); err != nil {\n    return fmt.Errorf(\"invalid CA bundle: %w\", err)\n}\nconfig, err := tls.GetClientTLSConfig(clientCert, clientKey, caCert, insecure)","preventionTips":["Validate downloaded CA files contain BEGIN CERTIFICATE PEM blocks","Don't save HTML error pages from proxied downloads as cert files","Convert DER certs to PEM before use (openssl x509 -inform der)","Keep CA bundles and keys in clearly named separate files"],"tags":["tls","pem","ca-certificate","parsing"],"backgroundTag":"invalid-pem-certificate","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}