{"record":{"id":"09b2fa58dbcd9f96","repo":"golang/go","slug":"tls-client-didn-t-provide-a-certificate","errorCode":null,"errorMessage":"tls: client didn't provide a certificate","messagePattern":"tls: client didn't provide a certificate","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/tls/handshake_server.go","lineNumber":967,"sourceCode":"\t\t\tc.sendAlert(alertDecodeError)\n\t\t\treturn errors.New(\"tls: failed to parse client certificate: \" + err.Error())\n\t\t}\n\t\tif certs[i].PublicKeyAlgorithm == x509.RSA {\n\t\t\tn := certs[i].PublicKey.(*rsa.PublicKey).N.BitLen()\n\t\t\tif max, ok := checkKeySize(n); !ok {\n\t\t\t\tc.sendAlert(alertBadCertificate)\n\t\t\t\treturn fmt.Errorf(\"tls: client sent certificate containing RSA key larger than %d bits\", max)\n\t\t\t}\n\t\t}\n\t}\n\n\tif len(certs) == 0 && requiresClientCert(c.config.ClientAuth) {\n\t\tif c.vers == VersionTLS13 {\n\t\t\tc.sendAlert(alertCertificateRequired)\n\t\t} else {\n\t\t\tc.sendAlert(alertHandshakeFailure)\n\t\t}\n\t\treturn errors.New(\"tls: client didn't provide a certificate\")\n\t}\n\n\tif c.config.ClientAuth >= VerifyClientCertIfGiven && len(certs) > 0 {\n\t\topts := x509.VerifyOptions{\n\t\t\tRoots:         c.config.ClientCAs,\n\t\t\tCurrentTime:   c.config.time(),\n\t\t\tIntermediates: x509.NewCertPool(),\n\t\t\tKeyUsages:     []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth},\n\t\t}\n\n\t\tfor _, cert := range certs[1:] {\n\t\t\topts.Intermediates.AddCert(cert)\n\t\t}\n\n\t\tchains, err := certs[0].Verify(opts)\n\t\tif err != nil {\n\t\t\tif _, ok := errors.AsType[x509.UnknownAuthorityError](err); ok {\n\t\t\t\tc.sendAlert(alertUnknownCA)","sourceCodeStart":949,"sourceCodeEnd":985,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/tls/handshake_server.go#L949-L985","documentation":"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).","triggerScenarios":"requiresClientCert(c.config.ClientAuth) is true and len(certs) == 0 — the client responded to CertificateRequest with an empty Certificate message.","commonSituations":"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.","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."],"exampleFix":"// before: client has no certificate configured\nhttp.Client{Transport: &http.Transport{\n    TLSClientConfig: &tls.Config{}, // no Certificates\n}}\n\n// after: load the mTLS client certificate\ncert, err := tls.LoadX509KeyPair(\"client.crt\", \"client.key\")\nif err != nil { return err }\nhttp.Client{Transport: &http.Transport{\n    TLSClientConfig: &tls.Config{\n        Certificates: []tls.Certificate{cert},\n    },\n}}","handlingStrategy":"validation","validationCode":"// Client: ensure a certificate is configured before connecting to an mTLS\n// server.\nif len(cfg.Certificates) == 0 && cfg.GetClientCertificate == nil {\n    return errors.New(\"server requires mTLS; no client certificate configured\")\n}","typeGuard":null,"tryCatchPattern":"// Client: catch and prompt for / load a certificate.\nif err != nil && strings.Contains(err.Error(), \"didn't provide a certificate\") {\n    cert, lerr := loadClientCert()\n    if lerr != nil { return err }\n    cfg.Certificates = []tls.Certificate{cert}\n    // retry\n}","preventionTips":["Pre-provision client certificates via config or secrets manager.","Implement GetClientCertificate for dynamic cert selection.","Document server-side mTLS policy to all client teams."],"tags":["tls","server-handshake","client-certificate","mtls","client-auth"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}