{"record":{"id":"9160d2adaa5fb92b","repo":"crowdsecurity/crowdsec","slug":"failed-to-append-ca-cert-file-s-w","errorCode":null,"errorMessage":"failed to append CA cert file %s: %w","messagePattern":"failed to append CA cert file (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/csconfig/database.go","lineNumber":176,"sourceCode":"\t\t} else {\n\t\t\tconnString = fmt.Sprintf(\"%s:%s@tcp(%s:%d)/%s\", d.User, d.Password, d.Host, d.Port, d.DbName)\n\t\t}\n\n\t\tif d.SSLMode != \"\" {\n\t\t\t// This will be overridden if a CA or client cert is provided\n\t\t\tparams.Set(\"tls\", d.SSLMode)\n\t\t}\n\n\t\tif d.SSLCACert != \"\" {\n\t\t\tcaCert, err := os.ReadFile(d.SSLCACert)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", fmt.Errorf(\"failed to read CA cert file %s: %w\", d.SSLCACert, err)\n\t\t\t}\n\t\t\tif tlsConfig.RootCAs == nil {\n\t\t\t\ttlsConfig.RootCAs = x509.NewCertPool()\n\t\t\t}\n\t\t\tif !tlsConfig.RootCAs.AppendCertsFromPEM(caCert) {\n\t\t\t\treturn \"\", fmt.Errorf(\"failed to append CA cert file %s: %w\", d.SSLCACert, err)\n\t\t\t}\n\t\t\tparams.Set(\"tls\", \"custom\")\n\t\t}\n\n\t\tif d.SSLClientCert != \"\" && d.SSLClientKey != \"\" {\n\t\t\tcert, err := tls.LoadX509KeyPair(d.SSLClientCert, d.SSLClientKey)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", fmt.Errorf(\"failed to load client cert/key pair: %w\", err)\n\t\t\t}\n\t\t\ttlsConfig.Certificates = []tls.Certificate{cert}\n\t\t\tparams.Set(\"tls\", \"custom\")\n\t\t}\n\n\t\tif params.Get(\"tls\") == \"custom\" {\n\t\t\t// Register the custom TLS config\n\t\t\terr := mysql.RegisterTLSConfig(\"custom\", tlsConfig)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", fmt.Errorf(\"failed to register custom TLS config: %w\", err)","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/crowdsecurity/crowdsec/blob/909b5157986a2b2c2163300fdaef5ed01289f7d2/pkg/csconfig/database.go#L158-L194","documentation":"After successfully reading the CA file, ConnectionString calls AppendCertsFromPEM on the x509 pool. If the content is not valid PEM (or contains no usable certificates), it returns false and the code wraps the (nil) read error as 'failed to append CA cert file %s: %w'. Note: the wrapped err here is nil, so the underlying cause is the file content itself.","triggerScenarios":"ssl_ca_cert points to an existing but non-PEM file: DER-encoded cert, an already-chained/binary file, empty file, or a private key instead of a certificate.","commonSituations":"Users export certs in DER format from Windows tooling; download HTML error page instead of cert; paste key material where a certificate is expected.","solutions":["Convert the certificate to PEM: `openssl x509 -inform der -in ca.der -out ca.pem`","Verify content: file should start with '-----BEGIN CERTIFICATE-----' (`head -1 ca.pem`)","Ensure you point at the CA certificate, not a client key or CSR"],"exampleFix":"// before\nopenssl x509 -inform der -in ca.cer -out ca.pem  # or check head -1\n// after\nssl_ca_cert: /etc/crowdsec/db/ca.pem  # PEM, '-----BEGIN CERTIFICATE-----'","handlingStrategy":"validation","validationCode":"pemBytes, _ := os.ReadFile(caPath); if block, _ := pem.Decode(pemBytes); block == nil || block.Type != \"CERTIFICATE\" { return fmt.Errorf(\"%s is not a PEM certificate\", caPath) }","typeGuard":null,"tryCatchPattern":"if _, err := dbCfg.ConnectionString(); err != nil { if strings.Contains(err.Error(), \"failed to append CA cert\") { log.Fatalf(\"CA file is not valid PEM: %v\", err) } }","preventionTips":["Always distribute CA certs in PEM format","Validate with `openssl x509 -in ca.pem -noout` before deploying","Confirm the first line is '-----BEGIN CERTIFICATE-----'"],"tags":["database","mysql","tls","certificate"],"backgroundTag":"invalid-certificate-format","analyzedSha":"909b5157986a2b2c2163300fdaef5ed01289f7d2","analyzedAt":"2026-09-06T12:27:26.012Z","contentChangedAt":"2026-09-06T12:27:26.012Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}