golang/go · error
tls: client didn't provide a certificate
Error message
tls: client didn't provide a certificate
What it means
The server requires a client certificate (ClientAuth is RequireAnyClientCert or RequireAndVerifyClientCert) but the client sent an empty certificate list. The server aborts with certificate_required (TLS 1.3) or handshake_failure (TLS 1.2).
Source
Thrown at src/crypto/tls/handshake_server.go:967
c.sendAlert(alertDecodeError)
return errors.New("tls: failed to parse client certificate: " + err.Error())
}
if certs[i].PublicKeyAlgorithm == x509.RSA {
n := certs[i].PublicKey.(*rsa.PublicKey).N.BitLen()
if max, ok := checkKeySize(n); !ok {
c.sendAlert(alertBadCertificate)
return fmt.Errorf("tls: client sent certificate containing RSA key larger than %d bits", max)
}
}
}
if len(certs) == 0 && requiresClientCert(c.config.ClientAuth) {
if c.vers == VersionTLS13 {
c.sendAlert(alertCertificateRequired)
} else {
c.sendAlert(alertHandshakeFailure)
}
return errors.New("tls: client didn't provide a certificate")
}
if c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {
opts := x509.VerifyOptions{
Roots: c.config.ClientCAs,
CurrentTime: c.config.time(),
Intermediates: x509.NewCertPool(),
KeyUsages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},
}
for _, cert := range certs[1:] {
opts.Intermediates.AddCert(cert)
}
chains, err := certs[0].Verify(opts)
if err != nil {
if _, ok := errors.AsType[x509.UnknownAuthorityError](err); ok {
c.sendAlert(alertUnknownCA)View on GitHub (pinned to b6b368adc5)
Solutions
- Provision the client with a certificate/key pair and configure tls.Config.Certificates or GetClientCertificate.
- If the client genuinely has no cert, relax the server's ClientAuth to VerifyClientCertIfGiven or NoClientCert.
- Ensure the client library honors the CertificateRequest callback.
- Distribute the client certificate and key via your secrets manager or config pipeline.
Example fix
// before: client has no certificate configured
http.Client{Transport: &http.Transport{
TLSClientConfig: &tls.Config{}, // no Certificates
}}
// after: load the mTLS client certificate
cert, err := tls.LoadX509KeyPair("client.crt", "client.key")
if err != nil { return err }
http.Client{Transport: &http.Transport{
TLSClientConfig: &tls.Config{
Certificates: []tls.Certificate{cert},
},
}} Defensive patterns
Strategy: validation
Validate before calling
// Client: ensure a certificate is configured before connecting to an mTLS
// server.
if len(cfg.Certificates) == 0 && cfg.GetClientCertificate == nil {
return errors.New("server requires mTLS; no client certificate configured")
} Try / catch
// Client: catch and prompt for / load a certificate.
if err != nil && strings.Contains(err.Error(), "didn't provide a certificate") {
cert, lerr := loadClientCert()
if lerr != nil { return err }
cfg.Certificates = []tls.Certificate{cert}
// retry
} Prevention
- Pre-provision client certificates via config or secrets manager.
- Implement GetClientCertificate for dynamic cert selection.
- Document server-side mTLS policy to all client teams.
When it happens
Trigger: requiresClientCert(c.config.ClientAuth) is true and len(certs) == 0 — the client responded to CertificateRequest with an empty Certificate message.
Common situations: The client has no certificate configured, ignores the server's CertificateRequest, is not prompted to select one, or its mTLS configuration is missing. Common when server-side mTLS policy is newly enforced but clients have not been updated.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- tls: client certificate used with invalid signature algorith
- tls: invalid signature by the client certificate: {err}
- tls: failed to parse client certificate: {err}
- client's certificate is not allowed in FIPS 140-3 mode
- tls: client certificate uses ML-DSA, which requires TLS 1.3
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/09b2fa58dbcd9f96.
Report an issue: GitHub.