{"record":{"id":"498a1989ce5e42ba","repo":"golang/go","slug":"tls-server-selected-an-invalid-psk-and-cipher-sui","errorCode":null,"errorMessage":"tls: server selected an invalid PSK and cipher suite pair","messagePattern":"tls: server selected an invalid PSK and cipher suite pair","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/tls/handshake_client_tls13.go","lineNumber":459,"sourceCode":"\tif !hs.serverHello.selectedIdentityPresent {\n\t\treturn nil\n\t}\n\n\tif int(hs.serverHello.selectedIdentity) >= len(hs.hello.pskIdentities) {\n\t\tc.sendAlert(alertIllegalParameter)\n\t\treturn errors.New(\"tls: server selected an invalid PSK\")\n\t}\n\n\tif len(hs.hello.pskIdentities) != 1 || hs.session == nil {\n\t\treturn c.sendAlert(alertInternalError)\n\t}\n\tpskSuite := cipherSuiteTLS13ByID(hs.session.cipherSuite)\n\tif pskSuite == nil {\n\t\treturn c.sendAlert(alertInternalError)\n\t}\n\tif pskSuite.hash != hs.suite.hash {\n\t\tc.sendAlert(alertIllegalParameter)\n\t\treturn errors.New(\"tls: server selected an invalid PSK and cipher suite pair\")\n\t}\n\n\ths.usingPSK = true\n\tc.didResume = true\n\tc.peerCertificates = hs.session.peerCertificates\n\tc.verifiedChains = hs.session.verifiedChains\n\tc.ocspResponse = hs.session.ocspResponse\n\tc.scts = hs.session.scts\n\treturn nil\n}\n\nfunc (hs *clientHandshakeStateTLS13) establishHandshakeKeys() error {\n\tc := hs.c\n\n\tke, err := keyExchangeForCurveID(hs.serverHello.serverShare.group)\n\tif err != nil {\n\t\tc.sendAlert(alertInternalError)\n\t\treturn err","sourceCodeStart":441,"sourceCodeEnd":477,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/tls/handshake_client_tls13.go#L441-L477","documentation":"Server selected a PSK whose original cipher suite hash does not match the hash of the cipher suite negotiated for this handshake. RFC 8446 §4.2.11 mandates the binder hash be consistent. Go sends `illegal_parameter`. Indicates inconsistent session resumption bookkeeping.","triggerScenarios":"selectedIdentity is in range and the resumed session's cipher suite (looked up via cipherSuiteTLS13ByID) has a hash that differs from the negotiated suite's hash.","commonSituations":"Session ticket cached under one cipher suite then resumed under another (e.g., server changed its suite preferences), a server cluster with divergent configs, or a buggy server that ignores the resumption-cipher-suite binding.","solutions":["Clear the client session cache (discard stale tickets) and retry the handshake fresh.","Align server-side cipher suite preferences so resumed and initial handshakes use the same suite family.","Disable 0-RTT/resumption temporarily to confirm the cause.","Report to the server operator if it persists across fresh sessions."],"exampleFix":"// before: stale tickets from a cipher-suite change cause mismatch\ncfg := &tls.Config{ClientSessionCache: tls.NewLRUClientSessionCache(100)}\n\n// after: flush cache so a fresh ticket is minted under the current suite\ncfg := &tls.Config{ClientSessionCache: tls.NewLRUClientSessionCache(0)}","handlingStrategy":"validation","validationCode":"// Pre-flight: pin cipher suites so resumed and initial handshakes use the same family.\ncfg.CipherSuites = []uint16{\n    tls.TLS_AES_128_GCM_SHA256,\n    tls.TLS_AES_256_GCM_SHA384,\n    tls.TLS_CHACHA20_POLY1305_SHA256,\n}","typeGuard":null,"tryCatchPattern":"if err := conn.Handshake(); err != nil {\n    if strings.Contains(err.Error(), \"invalid PSK and cipher suite pair\") {\n        cfg.ClientSessionCache = nil // stale ticket; retry fresh\n        return retryHandshake(addr, cfg)\n    }\n}","preventionTips":["Pin CipherSuites on both client and server so resumption is consistent.","Clear the session cache whenever cipher suite preferences change.","Avoid mixing TLS 1.3 sessions across load-balanced backends with divergent configs."],"tags":["tls","tls13","handshake","psk","session-resumption","cipher-suite","protocol-violation","network","go"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}