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

  1. 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)
  2. Set ClientAuth to tls.RequireAndVerifyClientCert (or at least RequestClientCert) in the server TLS config so certs are requested and enforced
  3. Check any TLS-terminating proxy forwards the client certificate to Vitess
  4. 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

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


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/b9f570c7957f2d48. Report an issue: GitHub.