vitessio/vitess · error
no client certs for connection
Error message
no client certs for connection
What it means
AuthServerClientCert.UserEntryWithPassword authenticates MySQL users by matching the username against the Common Name of the client's TLS certificate. This error means the connection presented no client certificate at all, so there is no Common Name to compare against; authentication cannot proceed.
Source
Thrown at go/mysql/auth_server_clientcert.go:91
}
// DefaultAuthMethodDescription returns always MysqlNativePassword
// for the client certificate authentication setup.
func (asl *AuthServerClientCert) DefaultAuthMethodDescription() AuthMethodDescription {
return MysqlNativePassword
}
// HandleUser is part of the UserValidator interface. We
// handle any user here since we don't check up front.
func (asl *AuthServerClientCert) HandleUser(user string) bool {
return true
}
// UserEntryWithPassword is part of the PlaintextStorage interface
func (asl *AuthServerClientCert) UserEntryWithPassword(conn *Conn, user string, password string, remoteAddr net.Addr) (Getter, error) {
userCerts := conn.GetTLSClientCerts()
if len(userCerts) == 0 {
return nil, errors.New("no client certs for connection")
}
commonName := userCerts[0].Subject.CommonName
if user != commonName {
return nil, fmt.Errorf("MySQL connection username '%v' does not match client cert common name '%v'", user, commonName)
}
return &StaticUserData{
Username: commonName,
Groups: userCerts[0].DNSNames,
}, nil
}
View on GitHub (pinned to 01a25a7d17)
Solutions
- Configure the client to present a client certificate signed by the server's CA (e.g. mysql --ssl-cert=client-cert.pem --ssl-key=client-key.pem)
- Set ClientAuth to tls.RequireAndVerifyClientCert (or at least RequestClientCert) in the server TLS config so certs are requested and enforced
- Check any TLS-terminating proxy forwards the client certificate to Vitess
- If client-cert auth is not intended, switch the auth server to password-based (AuthServerStatic/ldap etc.)
Example fix
// before (client) conn, err := mysql.Connect(ctx, params) // no client cert in params // after params.SslCert = "client-cert.pem" params.SslKey = "client-key.pem" conn, err := mysql.Connect(ctx, params)
Defensive patterns
Strategy: validation
Validate before calling
// client side, before connecting:
if certPEM == "" || keyPEM == "" { return errors.New("client-cert auth requires --ssl-cert/--ssl-key") }
// load and verify the cert has a Common Name matching the MySQL username Type guard
func hasClientCert(c *tls.ConnectionState) bool { return c != nil && len(c.PeerCertificates) > 0 } Try / catch
getter, err := asl.UserEntryWithPassword(conn, user, pass, addr)
if err != nil && strings.Contains(err.Error(), "no client certs") {
return nil, status.Errorf(codes.Unauthenticated, "client certificate required")
} Prevention
- Always configure client cert+key when AuthServerClientCert is enabled
- Set tls.ClientAuth to RequireAndVerifyClientCert on the server
- Keep the cert Common Name equal to the MySQL username
- Check TLS-terminating proxies forward client certificates
When it happens
Trigger: A client connects with TLS but without a client certificate (or with tls.Config that doesn't request/present one) while the auth server is AuthServerClientCert; conn.GetTLSClientCerts() returns an empty list.
Common situations: Client configured with only server-side CA verification (no cert/key in client config); mysql client run without --ssl-cert/--ssl-key; a proxy/load balancer terminating TLS and not forwarding the client cert; TLSClientAuth set to NoClientCert in server TLS config.
Related errors
- unexpected: query ended without no results and no error
- overflow
- mysqld >= 8.0.21 required to disable the redo log
- Last_SQL_Error: ${LastSQL_Error}, Last_IO_Error: ${LastIO_Er
- no port variable in mysql
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/b9f570c7957f2d48.
Report an issue: GitHub.