golang/go · error

tls: internal error: supportsCurve accepted unimplemented cu

Error message

tls: internal error: supportsCurve accepted unimplemented curve

What it means

Internal invariant violation in the Go crypto/tls package. The local `supportsCurve` check accepted a curve ID as supported, but `keyExchangeForCurveID` had no implementation for it. It is sent with an `internal_error` alert. This should never happen with an unmodified Go toolchain; encountering it implies a stdlib bug or a fork that added a CurveID without registering its key exchange.

Source

Thrown at src/crypto/tls/handshake_client_tls13.go:326

	// 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.
		hello.keyShares = hello.keyShares[:1]
	}

	if len(hello.pskIdentities) > 0 {
		pskSuite := cipherSuiteTLS13ByID(hs.session.cipherSuite)
		if pskSuite == nil {
			return c.sendAlert(alertInternalError)
		}
		if pskSuite.hash == hs.suite.hash {
			// Update binders and obfuscated_ticket_age.
			ticketAge := c.config.time().Sub(time.Unix(int64(hs.session.createdAt), 0))

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Upgrade to the latest stable Go toolchain; check the release notes for crypto/tls regressions.
  2. File an issue at golang.org/issue with the Go version and the curve ID; this is a stdlib defect.
  3. If running a fork (BoringCrypto/FIPS vendor branch), rebuild against the upstream matching version.
  4. Temporarily restrict CurvePreferences to widely-supported groups (X25519, CurveP256) to dodge the unimplemented curve.

Example fix

// before: rely on default curve set (may include an unimplemented entry on a forked build)
cfg := &tls.Config{}

// after: pin to well-supported curves only
cfg := &tls.Config{CurvePreferences: []tls.CurveID{tls.X25519, tls.CurveP256}}
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight: ensure every curve in CurvePreferences has a key-exchange impl in this build.
// There is no public API, so restrict to curves you know are implemented.
allowed := []tls.CurveID{tls.X25519, tls.CurveP256, tls.CurveP384, tls.CurveP521}
for _, c := range cfg.CurvePreferences {
    if !slices.Contains(allowed, c) {
        return fmt.Errorf("CurvePreferences contains unsupported curve %d; remove it", c)
    }
}

Try / catch

// This is a stdlib invariant violation; surface it loudly, do not retry.
if err := conn.Handshake(); err != nil {
    if strings.Contains(err.Error(), "supportsCurve accepted unimplemented curve") {
        log.Printf("FATAL: stdlib bug or forked build; Go version %s", runtime.Version())
    }
    return err
}

Prevention

When it happens

Trigger: Reached when the server's HelloRetryRequest selects a group that passed the supportedCurves Contains check (so Go thinks it supports it) but for which keyExchangeForCurveID returns an error. Only a Go stdlib regression or a custom build adding a CurveID without an implementation hits this.

Common situations: Running a patched/forked Go runtime, a broken FIPS or BoringCrypto build, or a future Go version where a curve constant was added but its KE function was not. Stock upstream Go should be reported as a bug.

Understand the failure class

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/1cd01e691728b3b2. Report an issue: GitHub.