{"record":{"id":"54802d962d42cb48","repo":"golang/go","slug":"tls-server-sent-encrypted-client-hello-retry-conf","errorCode":null,"errorMessage":"tls: server sent encrypted client hello retry configs after accepting encrypted client hello","messagePattern":"tls: server sent encrypted client hello retry configs after accepting encrypted client hello","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/tls/handshake_client_tls13.go","lineNumber":583,"sourceCode":"\tif hs.hello.earlyData && !encryptedExtensions.earlyData {\n\t\tc.quicRejectedEarlyData()\n\t}\n\tif encryptedExtensions.earlyData {\n\t\tif hs.session.cipherSuite != c.cipherSuite {\n\t\t\tc.sendAlert(alertHandshakeFailure)\n\t\t\treturn errors.New(\"tls: server accepted 0-RTT with the wrong cipher suite\")\n\t\t}\n\t\tif hs.session.alpnProtocol != c.clientProtocol {\n\t\t\tc.sendAlert(alertHandshakeFailure)\n\t\t\treturn errors.New(\"tls: server accepted 0-RTT with the wrong ALPN\")\n\t\t}\n\t}\n\tif hs.echContext != nil {\n\t\tif hs.echContext.echRejected {\n\t\t\ths.echContext.retryConfigs = encryptedExtensions.echRetryConfigs\n\t\t} else if encryptedExtensions.echRetryConfigs != nil {\n\t\t\tc.sendAlert(alertUnsupportedExtension)\n\t\t\treturn errors.New(\"tls: server sent encrypted client hello retry configs after accepting encrypted client hello\")\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc (hs *clientHandshakeStateTLS13) readServerCertificate() error {\n\tc := hs.c\n\n\t// Either a PSK or a certificate is always used, but not both.\n\t// See RFC 8446, Section 4.1.1.\n\tif hs.usingPSK {\n\t\t// Make sure the connection is still being verified whether or not this\n\t\t// is a resumption. Resumptions currently don't reverify certificates so\n\t\t// they don't call verifyServerCertificate. See Issue 31641.\n\t\tif c.config.VerifyConnection != nil {\n\t\t\tif err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil {\n\t\t\t\tc.sendAlert(alertBadCertificate)","sourceCodeStart":565,"sourceCodeEnd":601,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/tls/handshake_client_tls13.go#L565-L601","documentation":"Encrypted Client Hello (ECH) specific: the server accepted ECH (hs.echContext.echRejected is false) but still included ECH retry configs in EncryptedExtensions. RFC 9460 only permits retry configs when ECH was rejected. Go sends `unsupported_extension`. Indicates a server misusing the ECH retry_config field.","triggerScenarios":"Client offered ECH, server accepted it (inner SNI used), yet encryptedExtensions.echRetryConfigs is non-nil. Reached in processEncryptedExtensions when ECH is in use.","commonSituations":"Experimental/early ECH server implementations, fuzzed handshakes, or a server that always includes retry_configs. Mainstream ECH-capable servers gate retry_configs on rejection.","solutions":["Report to the server operator — retry_configs are rejection-only per RFC 9460.","Confirm ECH is actually being accepted (check the ECH status after the handshake) on a known-good peer.","Update the client and server ECH implementations to draft-compliant versions (ECH is still evolving).","Disable ECH (do not set Config.EncryptedClientHelloConfigList) if the server implementation is unreliable."],"exampleFix":"// before: ECH configured against a server with buggy retry-config handling\ncfg := &tls.Config{EncryptedClientHelloConfigList: echList}\n\n// after: disable ECH until the server is fixed\ncfg := &tls.Config{}","handlingStrategy":"validation","validationCode":"// Pre-flight: ECH is still maturing; only enable it against peers known to implement RFC 9460 correctly.\nif !echCapablePeer {\n    cfg.EncryptedClientHelloConfigList = nil\n}","typeGuard":null,"tryCatchPattern":"if err := conn.Handshake(); err != nil {\n    if strings.Contains(err.Error(), \"encrypted client hello retry configs after accepting\") {\n        cfg.EncryptedClientHelloConfigList = nil // disable ECH for this peer\n        return retryHandshake(addr, cfg)\n    }\n}","preventionTips":["Track ECH draft/RFC compliance of peers before enabling ECH.","Update both client and server ECH implementations in lockstep.","Log ECH outcomes to detect servers with buggy retry-config logic."],"tags":["tls","tls13","ech","encrypted-client-hello","encrypted-extensions","protocol-violation","network","go"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:17:08.281Z"}