gofr-dev/gofr · error
failed to load client certificate: %w
Error message
failed to load client certificate: %w
What it means
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.
Source
Thrown at pkg/gofr/datasource/sql/sql.go:538
caCertPool := x509.NewCertPool()
if !caCertPool.AppendCertsFromPEM(caCert) {
return errFailedCACerts
}
tlsConfig := &tls.Config{
RootCAs: caCertPool,
ServerName: dbConfig.HostName,
MinVersion: tls.VersionTLS12,
}
// Optional: Support client certificates (mutual TLS)
clientCertPath := os.Getenv("DB_TLS_CLIENT_CERT")
clientKeyPath := os.Getenv("DB_TLS_CLIENT_KEY")
if clientCertPath != "" && clientKeyPath != "" {
clientCert, err := tls.LoadX509KeyPair(clientCertPath, clientKeyPath)
if err != nil {
return fmt.Errorf("failed to load client certificate: %w", err)
}
tlsConfig.Certificates = []tls.Certificate{clientCert}
logger.Debug("loaded client certificate for mutual TLS")
}
return mysql.RegisterTLSConfig("custom", tlsConfig)
}
func getServerName(hostname string) string {
// For localhost/127.0.0.1, use "localhost" explicitly
if hostname == "127.0.0.1" || hostname == "::1" {
return localhost
}
return hostname
}View on GitHub (pinned to 187eb24962)
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.
Example fix
// before DB_TLS_CLIENT_CERT=/certs/old-client.crt DB_TLS_CLIENT_KEY=/certs/new-client.key // mismatched pair // after DB_TLS_CLIENT_CERT=/certs/client.crt DB_TLS_CLIENT_KEY=/certs/client.key // matching pair
Defensive patterns
Strategy: validation
Validate before calling
certPEM, _ := os.ReadFile(os.Getenv("DB_TLS_CLIENT_CERT"))
keyPEM, _ := os.ReadFile(os.Getenv("DB_TLS_CLIENT_KEY"))
if _, err := tls.X509KeyPair(certPEM, keyPEM); err != nil {
return fmt.Errorf("client cert/key invalid or mismatched: %w", err)
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- failed to append CA certificate
- failed to read CA certificate from %s: %w
- invalid certificate file
- invalid key file
- %w : %v
AI-assisted analysis of gofr-dev/gofr@187eb24962 (2026-09-01).
Data as JSON: /api/errors/cf3fbcad2aaf61a1.
Report an issue: GitHub.