{"record":{"id":"3c0585d35afe28f2","repo":"golang/go","slug":"tls-server-selected-tls-1-3-in-a-renegotiation","errorCode":null,"errorMessage":"tls: server selected TLS 1.3 in a renegotiation","messagePattern":"tls: server selected TLS 1\\.3 in a renegotiation","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/tls/handshake_client_tls13.go","lineNumber":53,"sourceCode":"\tsentDummyCCS  bool\n\tsuite         *cipherSuiteTLS13\n\ttranscript    hash.Hash\n\tmasterSecret  *tls13.MasterSecret\n\ttrafficSecret []byte // client_application_traffic_secret_0\n\n\techContext *echClientContext\n}\n\n// handshake requires hs.c, hs.hello, hs.serverHello, hs.keyShareKeys, and,\n// optionally, hs.session, hs.earlySecret and hs.binderKey to be set.\nfunc (hs *clientHandshakeStateTLS13) handshake() error {\n\tc := hs.c\n\n\t// The server must not select TLS 1.3 in a renegotiation. See RFC 8446,\n\t// sections 4.1.2 and 4.1.3.\n\tif c.handshakes > 0 {\n\t\tc.sendAlert(alertProtocolVersion)\n\t\treturn errors.New(\"tls: server selected TLS 1.3 in a renegotiation\")\n\t}\n\n\t// Consistency check on the presence of a keyShare and its parameters.\n\tif hs.keyShareKeys == nil || (hs.keyShareKeys.ecdhe == nil && hs.keyShareKeys.mlkem == nil) ||\n\t\tlen(hs.hello.keyShares) == 0 {\n\t\treturn c.sendAlert(alertInternalError)\n\t}\n\n\tif err := hs.checkServerHelloOrHRR(); err != nil {\n\t\treturn err\n\t}\n\n\ths.transcript = hs.suite.hash.New()\n\n\tif err := transcriptMsg(hs.hello, hs.transcript); err != nil {\n\t\treturn err\n\t}\n","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/tls/handshake_client_tls13.go#L35-L71","documentation":"Thrown in clientHandshakeStateTLS13.handshake() when the server selects TLS 1.3 during a renegotiation (c.handshakes > 0). RFC 8446 sections 4.1.2 and 4.1.3 explicitly prohibit renegotiation in TLS 1.3 — TLS 1.3 replaces it with post-handshake authentication and KeyUpdate.","triggerScenarios":"Triggered when c.handshakes > 0 and the server's selected version is TLS 1.3. The client sends alertProtocolVersion and aborts.","commonSituations":"Calling Conn.Renegotiate() on a connection that the server then negotiates at TLS 1.3. Custom connection pooling that attempts renegotiation for re-authentication. Server-initiated renegotiation on an already-established TLS 1.3 connection. Code written for TLS 1.2 renegotiation that breaks under TLS 1.3.","solutions":["Do not renegotiate TLS 1.3 connections — use post-handshake authentication (tls.Conn.VerifyPeerCertificate callback) or KeyUpdate instead.","Replace renegotiation-based connection reuse with a connection pool that creates fresh TLS connections.","Pin MaxVersion to tls.VersionTLS12 if renegotiation is a hard requirement and cannot be refactored away.","Refactor the re-authentication pattern: close and re-dial instead of renegotiating."],"exampleFix":"// before — renegotiation fails on TLS 1.3\nconn := // existing TLS connection\nerr := conn.Renegotiate(tls.RenegotiateOnceAsClient)\n\n// after — establish a fresh connection instead\nconn.Close()\nconn, err = tls.Dial(\"tcp\", addr, config)","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Renegotiation errors are untyped strings\nerr := conn.Renegotiate(tls.RenegotiateOnceAsClient)\nif err != nil {\n    if strings.Contains(err.Error(), \"server selected TLS 1.3 in a renegotiation\") {\n        // TLS 1.3 does not support renegotiation — dial a fresh connection\n        conn.Close()\n        conn, err = tls.Dial(\"tcp\", addr, config)\n    }\n}","preventionTips":["Never call Renegotiate() on connections that may negotiate TLS 1.3.","Use connection pools with fresh handshakes instead of renegotiation.","Pin MaxVersion to TLS 1.2 only if renegotiation is a hard requirement.","Refactor re-authentication to use new connections."],"tags":["tls","go","tls13","renegotiation","protocol-violation"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}