{"record":{"id":"cf3fbcad2aaf61a1","repo":"gofr-dev/gofr","slug":"failed-to-load-client-certificate-w","errorCode":null,"errorMessage":"failed to load client certificate: %w","messagePattern":"failed to load client certificate: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/gofr/datasource/sql/sql.go","lineNumber":538,"sourceCode":"\tcaCertPool := x509.NewCertPool()\n\tif !caCertPool.AppendCertsFromPEM(caCert) {\n\t\treturn errFailedCACerts\n\t}\n\n\ttlsConfig := &tls.Config{\n\t\tRootCAs:    caCertPool,\n\t\tServerName: dbConfig.HostName,\n\t\tMinVersion: tls.VersionTLS12,\n\t}\n\n\t// Optional: Support client certificates (mutual TLS)\n\tclientCertPath := os.Getenv(\"DB_TLS_CLIENT_CERT\")\n\tclientKeyPath := os.Getenv(\"DB_TLS_CLIENT_KEY\")\n\n\tif clientCertPath != \"\" && clientKeyPath != \"\" {\n\t\tclientCert, err := tls.LoadX509KeyPair(clientCertPath, clientKeyPath)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to load client certificate: %w\", err)\n\t\t}\n\n\t\ttlsConfig.Certificates = []tls.Certificate{clientCert}\n\n\t\tlogger.Debug(\"loaded client certificate for mutual TLS\")\n\t}\n\n\treturn mysql.RegisterTLSConfig(\"custom\", tlsConfig)\n}\n\nfunc getServerName(hostname string) string {\n\t// For localhost/127.0.0.1, use \"localhost\" explicitly\n\tif hostname == \"127.0.0.1\" || hostname == \"::1\" {\n\t\treturn localhost\n\t}\n\n\treturn hostname\n}","sourceCodeStart":520,"sourceCodeEnd":556,"githubUrl":"https://github.com/gofr-dev/gofr/blob/187eb24962502e91f1fee856230670958b66e89c/pkg/gofr/datasource/sql/sql.go#L520-L556","documentation":"Raised in registerMySQLTLSConfig when DB_TLS_CLIENT_CERT and DB_TLS_CLIENT_KEY are both set but tls.LoadX509KeyPair fails to parse them as a matching client key pair. gofr uses this to configure mutual TLS (mTLS) for MySQL; a bad pair aborts TLS setup.","triggerScenarios":"NewSQL (mysql dialect) with both DB_TLS_CLIENT_CERT and DB_TLS_CLIENT_KEY set to files that don't exist, are malformed PEM, or where the cert and key don't match (different key pairs).","commonSituations":"Cert renewed but key not updated (or vice versa), swapped cert/key env values, encrypted private key, DER-format client cert, or missing files in the container.","solutions":["Verify the cert and key match: compare modulus (openssl x509 -noout -modulus; openssl rsa -noout -modulus).","Check both files exist, are readable, and are valid PEM (openssl x509 -in cert; openssl rsa -in key).","Ensure the key is unencrypted or re-export without a passphrase.","Fix DB_TLS_CLIENT_CERT / DB_TLS_CLIENT_KEY env values if swapped or mistyped."],"exampleFix":"// before\nDB_TLS_CLIENT_CERT=/certs/old-client.crt\nDB_TLS_CLIENT_KEY=/certs/new-client.key  // mismatched pair\n// after\nDB_TLS_CLIENT_CERT=/certs/client.crt\nDB_TLS_CLIENT_KEY=/certs/client.key  // matching pair","handlingStrategy":"validation","validationCode":"certPEM, _ := os.ReadFile(os.Getenv(\"DB_TLS_CLIENT_CERT\"))\nkeyPEM, _ := os.ReadFile(os.Getenv(\"DB_TLS_CLIENT_KEY\"))\nif _, err := tls.X509KeyPair(certPEM, keyPEM); err != nil {\n    return fmt.Errorf(\"client cert/key invalid or mismatched: %w\", err)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Renew cert and key together and store them as a pair.","Verify match with openssl before deploying (compare moduli).","Use unencrypted keys for automated services."],"tags":["tls","mtls","mysql","certificates"],"backgroundTag":"client-certificate-load-failed","analyzedSha":"187eb24962502e91f1fee856230670958b66e89c","analyzedAt":"2026-09-01T20:34:54.554Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}