golang/go · error
tls: server selected unsupported group
Error message
tls: server selected unsupported group
What it means
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.
Source
Thrown at src/crypto/tls/handshake_client_tls13.go:315
return errors.New("tls: server sent an unnecessary HelloRetryRequest message")
}
if hs.serverHello.cookie != nil {
hello.cookie = hs.serverHello.cookie
}
if hs.serverHello.serverShare.group != 0 {
c.sendAlert(alertDecodeError)
return errors.New("tls: received malformed key_share extension")
}
// If the server sent a key_share extension selecting a group, ensure it's
// a group we advertised but did not send a key share for, and send a key
// share for it this time.
if curveID := hs.serverHello.selectedGroup; curveID != 0 {
if !slices.Contains(hello.supportedCurves, curveID) {
c.sendAlert(alertIllegalParameter)
return errors.New("tls: server selected unsupported group")
}
if slices.ContainsFunc(hs.hello.keyShares, func(ks keyShare) bool {
return ks.group == curveID
}) {
c.sendAlert(alertIllegalParameter)
return errors.New("tls: server sent an unnecessary HelloRetryRequest key_share")
}
ke, err := keyExchangeForCurveID(curveID)
if err != nil {
c.sendAlert(alertInternalError)
return errors.New("tls: internal error: supportsCurve accepted unimplemented curve")
}
hs.keyShareKeys, hello.keyShares, err = ke.keyShares(c.config.rand())
if err != nil {
c.sendAlert(alertInternalError)
return err
}
// Do not send the fallback ECDH key share in a HRR response.View on GitHub (pinned to b6b368adc5)
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.
Example fix
// before — only X25519 advertised, server wants P-256
config := &tls.Config{
CurvePreferences: []tls.CurveID{tls.X25519},
}
// after — use defaults or include multiple curves
config := &tls.Config{
// CurvePreferences nil = Go defaults (X25519, P-256, P-384)
}
// or explicitly:
// CurvePreferences: []tls.CurveID{tls.X25519, tls.CurveP256, tls.CurveP384} Defensive patterns
Strategy: validation
Validate before calling
// Validate curve preferences before connecting
func validateCurvePreferences(config *tls.Config) error {
if config.CurvePreferences == nil {
return nil // nil = Go defaults, always OK
}
commonCurves := map[tls.CurveID]bool{
tls.X25519: true,
tls.CurveP256: true,
tls.CurveP384: true,
}
for _, c := range config.CurvePreferences {
if commonCurves[c] {
return nil // at least one common curve
}
}
return fmt.Errorf("CurvePreferences excludes all common curves (X25519, P-256, P-384)")
} Try / catch
conn, err := tls.Dial("tcp", addr, config)
if err != nil {
if strings.Contains(err.Error(), "server selected unsupported group") {
// Reset to defaults and retry
config.CurvePreferences = nil
conn, err = tls.Dial("tcp", addr, config)
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- tls: received malformed key_share extension
- tls: server changed cipher suite after a HelloRetryRequest
- tls: server chose an unconfigured cipher suite
- tls: malformed encrypted client hello extension
- tls: server sent an unnecessary HelloRetryRequest message
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/1ea94424d75f308b.
Report an issue: GitHub.