{"record":{"id":"bb5f4e5c6d0930fa","repo":"t8y2/dbx","slug":"failed-to-parse-ca-certificate-at-s","errorCode":null,"errorMessage":"failed to parse CA certificate at %s","messagePattern":"failed to parse CA certificate at (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agents/drivers/etcd-go/client.go","lineNumber":282,"sourceCode":"\t\tvalue, err := strconv.Atoi(entry[separator+1:])\n\t\tif err != nil {\n\t\t\treturn fallback\n\t\t}\n\t\treturn value\n\t}\n\treturn fallback\n}\n\nfunc tlsConfigFor(connection connectionParams) (*tls.Config, error) {\n\ttlsConfig := &tls.Config{}\n\tif ca := strings.TrimSpace(connection.CACertPath); ca != \"\" {\n\t\tauthorityPEM, err := os.ReadFile(ca)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tpool := x509.NewCertPool()\n\t\tif !pool.AppendCertsFromPEM(authorityPEM) {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse CA certificate at %s\", ca)\n\t\t}\n\t\ttlsConfig.RootCAs = pool\n\t}\n\tcertPath := firstNonBlank(connection.ClientCertPath, connection.CertPath)\n\tkeyPath := firstNonBlank(connection.ClientKeyPath, connection.KeyPath)\n\tif (certPath == \"\") != (keyPath == \"\") {\n\t\treturn nil, errors.New(\"Client certificate and key must be provided together\")\n\t}\n\tif certPath != \"\" {\n\t\tpair, err := tls.LoadX509KeyPair(certPath, keyPath)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tif len(pair.Certificate) > 0 {\n\t\t\tpair.Leaf, err = x509.ParseCertificate(pair.Certificate[0])\n\t\t\tif err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}","sourceCodeStart":264,"sourceCodeEnd":300,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/etcd-go/client.go#L264-L300","documentation":"tlsConfigFor builds a TLS configuration for the etcd client connection. When a CA certificate file is specified, it reads the PEM file and attempts to append its certificates to an x509 CertPool; if AppendCertsFromPEM fails, no usable certificates were found in the file and the library aborts with this error rather than silently building an insecure/empty trust store.","triggerScenarios":"tlsConfigFor is called (via buildClient) with connection.CAPath set to a file that exists and is readable, but whose bytes contain no parseable PEM certificate blocks (e.g. empty file, a private key, a chain of intermediates only, DER-encoded cert, or HTML error page).","commonSituations":"Pointing CAPath at a server cert instead of the CA bundle; copying a certificate through a tool that mangled it (e.g. text-mode transfer, truncated file); using a DER .crt file where PEM is required; passing a Kubernetes secret key that is empty or contains a key rather than a cert; stale mount/secret after rotation leaving a zero-byte file.","solutions":["Verify the file at the CA path contains a PEM block starting with '-----BEGIN CERTIFICATE-----'; open it and check the first line.","If the file is DER-encoded, convert it: openssl x509 -inform DER -in ca.crt -out ca.pem.","Ensure you are pointing at the CA/issuer bundle, not the server or client certificate; re-export from your PKI or cluster (e.g. kubectl get secret ... -o jsonpath='{.data.ca\\.crt}' | base64 -d).","Check the file is not empty or truncated (ls -l, compare byte size with source); re-copy in binary mode.","Confirm the code reads the correct path: CAPath vs ClientCertPath mix-ups resolve via firstNonBlank; fix the connection config field."],"exampleFix":"// before\nconnection.CAPath = \"/etc/pki/server.crt\" // DER-encoded, AppendCertsFromPEM fails\n// after\n// convert to PEM first: openssl x509 -inform DER -in server.crt -out ca.pem\nconnection.CAPath = \"/etc/pki/ca.pem\"","handlingStrategy":"validation","validationCode":"func caFileLooksValid(path string) error {\n\tb, err := os.ReadFile(path)\n\tif err != nil {\n\t\treturn err\n\t}\n\tif !bytes.Contains(b, []byte(\"-----BEGIN CERTIFICATE-----\")) {\n\t\treturn fmt.Errorf(\"%s contains no PEM certificate block\", path)\n\t}\n\tif !x509.NewCertPool().AppendCertsFromPEM(b) {\n\t\treturn fmt.Errorf(\"%s has no parseable certificates\", path)\n\t}\n\treturn nil\n}\n// call caFileLooksValid(connection.CAPath) before buildClient","typeGuard":"func isPEMCert(data []byte) bool {\n\tblock, _ := pem.Decode(data)\n\treturn block != nil && block.Type == \"CERTIFICATE\"\n}","tryCatchPattern":null,"preventionTips":["Keep CA material in PEM format; convert DER certs with openssl x509 -inform DER.","Mount Kubernetes TLS secrets at type kubernetes.io/tls or use ca.crt from configmaps, and verify keys after rotation.","Add a startup preflight that loads and parses the CA file before building the client.","Never copy certificates through text-mode transfers; compare checksums after copying."],"tags":["tls","configuration","certificates","etcd"],"backgroundTag":"tls-certificate-parse-failed","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}