{"record":{"id":"e006cfb225e9bf26","repo":"golang/go","slug":"tls-unexpected-encrypted-client-hello-extension-i","errorCode":null,"errorMessage":"tls: unexpected encrypted client hello extension in server hello despite ECH being accepted","messagePattern":"tls: unexpected encrypted client hello extension in server hello despite ECH being accepted","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/tls/handshake_client_tls13.go","lineNumber":108,"sourceCode":"\t\tconfTranscript.Write(hs.serverHello.original[:30])\n\t\tconfTranscript.Write(make([]byte, 8))\n\t\tconfTranscript.Write(hs.serverHello.original[38:])\n\t\th := hs.suite.hash.New\n\t\tprk, err := hkdf.Extract(h, hs.echContext.innerHello.random, nil)\n\t\tif err != nil {\n\t\t\tc.sendAlert(alertInternalError)\n\t\t\treturn err\n\t\t}\n\t\tacceptConfirmation := tls13.ExpandLabel(h, prk, \"ech accept confirmation\", confTranscript.Sum(nil), 8)\n\t\tif subtle.ConstantTimeCompare(acceptConfirmation, hs.serverHello.random[len(hs.serverHello.random)-8:]) == 1 {\n\t\t\ths.hello = hs.echContext.innerHello\n\t\t\tc.serverName = c.config.ServerName\n\t\t\ths.transcript = hs.echContext.innerTranscript\n\t\t\tc.echAccepted = true\n\n\t\t\tif hs.serverHello.encryptedClientHello != nil {\n\t\t\t\tc.sendAlert(alertUnsupportedExtension)\n\t\t\t\treturn errors.New(\"tls: unexpected encrypted client hello extension in server hello despite ECH being accepted\")\n\t\t\t}\n\n\t\t\tif hs.hello.serverName == \"\" && hs.serverHello.serverNameAck {\n\t\t\t\tc.sendAlert(alertUnsupportedExtension)\n\t\t\t\treturn errors.New(\"tls: unexpected server_name extension in server hello\")\n\t\t\t}\n\t\t} else {\n\t\t\ths.echContext.echRejected = true\n\t\t}\n\t}\n\n\tif err := transcriptMsg(hs.serverHello, hs.transcript); err != nil {\n\t\treturn err\n\t}\n\n\tc.buffering = true\n\tif err := hs.processServerHello(); err != nil {\n\t\treturn err","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/tls/handshake_client_tls13.go#L90-L126","documentation":"Thrown during TLS 1.3 ECH (Encrypted Client Hello) processing when the server's accept_confirmation value matches (ECH was accepted) but the ServerHello still contains an encrypted_client_hello extension. Per the ECH specification, once acceptance is confirmed, the server must not include the ECH extension in ServerHello.","triggerScenarios":"Triggered inside checkServerHelloOrHRR() when hs.serverHello.encryptedClientHello is non-nil after ECH acceptance was confirmed via constant-time comparison of the accept_confirmation value. The client sends alertUnsupportedExtension.","commonSituations":"Server bug in ECH implementation that includes the extension after acceptance. Mismatched ECH draft versions between client and server causing divergent handling. Experimental or non-standard ECH server implementation.","solutions":["Verify the ECH draft version on client and server match — ECH is still evolving through IETF drafts.","If you control the server, ensure it omits encrypted_client_hello from ServerHello after ECH acceptance.","If ECH is not required, remove config.EncryptedClientHelloConfigList from the client config to disable ECH entirely.","Report the issue to the server's ECH implementation maintainer."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"conn, err := tls.Dial(\"tcp\", addr, config)\nif err != nil {\n    if strings.Contains(err.Error(), \"ech being accepted\") {\n        // Server bug in ECH handling — disable ECH and retry\n        config.EncryptedClientHelloConfigList = nil\n        conn, err = tls.Dial(\"tcp\", addr, config)\n    }\n}","preventionTips":["Verify ECH draft version compatibility between client and server.","Disable ECH (remove EncryptedClientHelloConfigList) if the server's ECH implementation is buggy.","Test ECH against known-good ECH servers (e.g. Cloudflare) before deploying."],"tags":["tls","go","ech","tls13","privacy","protocol-violation"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:31:55.035Z"}