{"record":{"id":"1cd01e691728b3b2","repo":"golang/go","slug":"tls-internal-error-supportscurve-accepted-unimpl","errorCode":null,"errorMessage":"tls: internal error: supportsCurve accepted unimplemented curve","messagePattern":"tls: internal error: supportsCurve accepted unimplemented curve","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/crypto/tls/handshake_client_tls13.go","lineNumber":326,"sourceCode":"\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.\n\t\thello.keyShares = hello.keyShares[:1]\n\t}\n\n\tif len(hello.pskIdentities) > 0 {\n\t\tpskSuite := cipherSuiteTLS13ByID(hs.session.cipherSuite)\n\t\tif pskSuite == nil {\n\t\t\treturn c.sendAlert(alertInternalError)\n\t\t}\n\t\tif pskSuite.hash == hs.suite.hash {\n\t\t\t// Update binders and obfuscated_ticket_age.\n\t\t\tticketAge := c.config.time().Sub(time.Unix(int64(hs.session.createdAt), 0))","sourceCodeStart":308,"sourceCodeEnd":344,"githubUrl":"https://github.com/golang/go/blob/b6b368adc57c96c3151d224d172029f233ead2c3/src/crypto/tls/handshake_client_tls13.go#L308-L344","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Upgrade to the latest stable Go toolchain; check the release notes for crypto/tls regressions.","File an issue at golang.org/issue with the Go version and the curve ID; this is a stdlib defect.","If running a fork (BoringCrypto/FIPS vendor branch), rebuild against the upstream matching version.","Temporarily restrict CurvePreferences to widely-supported groups (X25519, CurveP256) to dodge the unimplemented curve."],"exampleFix":"// before: rely on default curve set (may include an unimplemented entry on a forked build)\ncfg := &tls.Config{}\n\n// after: pin to well-supported curves only\ncfg := &tls.Config{CurvePreferences: []tls.CurveID{tls.X25519, tls.CurveP256}}","handlingStrategy":"validation","validationCode":"// Pre-flight: ensure every curve in CurvePreferences has a key-exchange impl in this build.\n// There is no public API, so restrict to curves you know are implemented.\nallowed := []tls.CurveID{tls.X25519, tls.CurveP256, tls.CurveP384, tls.CurveP521}\nfor _, c := range cfg.CurvePreferences {\n    if !slices.Contains(allowed, c) {\n        return fmt.Errorf(\"CurvePreferences contains unsupported curve %d; remove it\", c)\n    }\n}","typeGuard":null,"tryCatchPattern":"// This is a stdlib invariant violation; surface it loudly, do not retry.\nif err := conn.Handshake(); err != nil {\n    if strings.Contains(err.Error(), \"supportsCurve accepted unimplemented curve\") {\n        log.Printf(\"FATAL: stdlib bug or forked build; Go version %s\", runtime.Version())\n    }\n    return err\n}","preventionTips":["Pin CurvePreferences to widely-supported groups rather than relying on defaults.","Track the Go version in deployment metadata so stdlib regressions are easy to correlate.","Avoid forked/FIPS builds that add CurveID constants without key-exchange implementations."],"tags":["tls","tls13","stdlib","internal-error","crypto","go"],"backgroundTag":null,"analyzedSha":"b6b368adc57c96c3151d224d172029f233ead2c3","analyzedAt":"2026-08-12T00:22:02.250Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}