{"record":{"id":"1ea94424d75f308b","repo":"golang/go","slug":"tls-server-selected-unsupported-group","errorCode":null,"errorMessage":"tls: server selected unsupported group","messagePattern":"tls: server selected unsupported group","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/tls/handshake_client_tls13.go","lineNumber":315,"sourceCode":"\t\treturn errors.New(\"tls: server sent an unnecessary HelloRetryRequest message\")\n\t}\n\n\tif hs.serverHello.cookie != nil {\n\t\thello.cookie = hs.serverHello.cookie\n\t}\n\n\tif hs.serverHello.serverShare.group != 0 {\n\t\tc.sendAlert(alertDecodeError)\n\t\treturn errors.New(\"tls: received malformed key_share extension\")\n\t}\n\n\t// If the server sent a key_share extension selecting a group, ensure it's\n\t// a group we advertised but did not send a key share for, and send a key\n\t// share for it this time.\n\tif curveID := hs.serverHello.selectedGroup; curveID != 0 {\n\t\tif !slices.Contains(hello.supportedCurves, curveID) {\n\t\t\tc.sendAlert(alertIllegalParameter)\n\t\t\treturn errors.New(\"tls: server selected unsupported group\")\n\t\t}\n\t\tif slices.ContainsFunc(hs.hello.keyShares, func(ks keyShare) bool {\n\t\t\treturn ks.group == curveID\n\t\t}) {\n\t\t\tc.sendAlert(alertIllegalParameter)\n\t\t\treturn errors.New(\"tls: server sent an unnecessary HelloRetryRequest key_share\")\n\t\t}\n\t\tke, err := keyExchangeForCurveID(curveID)\n\t\tif err != nil {\n\t\t\tc.sendAlert(alertInternalError)\n\t\t\treturn errors.New(\"tls: internal error: supportsCurve accepted unimplemented curve\")\n\t\t}\n\t\ths.keyShareKeys, hello.keyShares, err = ke.keyShares(c.config.rand())\n\t\tif err != nil {\n\t\t\tc.sendAlert(alertInternalError)\n\t\t\treturn err\n\t\t}\n\t\t// Do not send the fallback ECDH key share in a HRR response.","sourceCodeStart":297,"sourceCodeEnd":333,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/tls/handshake_client_tls13.go#L297-L333","documentation":"Thrown during HelloRetryRequest processing when the server's selected_group in key_share is a group the client did not advertise in its supported_groups (supportedCurves) list. The server requested a key share for an unsupported group.","triggerScenarios":"Triggered when slices.Contains(hello.supportedCurves, curveID) returns false for the server-selected curveID. The client sends alertIllegalParameter. The server asked for a key share on a curve the client doesn't support or didn't advertise.","commonSituations":"Client tls.Config.CurvePreferences is explicitly restricted to a subset that excludes the server's preferred group (e.g. only X25519 but server wants P-384). Client and server group configuration mismatch. Server bug selecting an unadvertised group. Older Go version lacking support for newer groups.","solutions":["Check tls.Config.CurvePreferences — if set, ensure it includes common groups: tls.X25519, tls.CurveP256, tls.CurveP384.","Leave CurvePreferences nil to use Go's defaults (recommended): X25519, P-256, P-384.","Verify the server's preferred groups and ensure client supports at least one.","Update Go to a recent version for the latest curve support."],"exampleFix":"// before — only X25519 advertised, server wants P-256\nconfig := &tls.Config{\n    CurvePreferences: []tls.CurveID{tls.X25519},\n}\n\n// after — use defaults or include multiple curves\nconfig := &tls.Config{\n    // CurvePreferences nil = Go defaults (X25519, P-256, P-384)\n}\n// or explicitly:\n// CurvePreferences: []tls.CurveID{tls.X25519, tls.CurveP256, tls.CurveP384}","handlingStrategy":"validation","validationCode":"// Validate curve preferences before connecting\nfunc validateCurvePreferences(config *tls.Config) error {\n    if config.CurvePreferences == nil {\n        return nil // nil = Go defaults, always OK\n    }\n    commonCurves := map[tls.CurveID]bool{\n        tls.X25519:    true,\n        tls.CurveP256: true,\n        tls.CurveP384: true,\n    }\n    for _, c := range config.CurvePreferences {\n        if commonCurves[c] {\n            return nil // at least one common curve\n        }\n    }\n    return fmt.Errorf(\"CurvePreferences excludes all common curves (X25519, P-256, P-384)\")\n}","typeGuard":null,"tryCatchPattern":"conn, err := tls.Dial(\"tcp\", addr, config)\nif err != nil {\n    if strings.Contains(err.Error(), \"server selected unsupported group\") {\n        // Reset to defaults and retry\n        config.CurvePreferences = nil\n        conn, err = tls.Dial(\"tcp\", addr, config)\n    }\n}","preventionTips":["Leave tls.Config.CurvePreferences as nil to use Go's recommended defaults (X25519, P-256, P-384).","If restricting curves, always include at least X25519 and P-256.","Verify server group preferences and ensure client supports them.","Update Go for the latest curve support."],"tags":["tls","go","tls13","key-share","hello-retry-request","configuration"],"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:17:08.281Z"}