golang/go · warning
no mutually supported protocol versions
Error message
no mutually supported protocol versions
What it means
Thrown by ClientHelloInfo.SupportsCertificate when config.mutualVersion finds no protocol version common to client and server. SupportsCertificate checks whether a given certificate is usable for the ClientHello; if the version negotiation fails first, no certificate can be selected, so this error is returned.
Source
Thrown at src/crypto/tls/common.go:1401
// callback, this method will take into account the associated [Config]. Note that
// if GetConfigForClient returns a different [Config], the change can't be
// accounted for by this method.
//
// This function will call x509.ParseCertificate unless c.Leaf is set, which can
// incur a significant performance cost.
func (chi *ClientHelloInfo) SupportsCertificate(c *Certificate) error {
// Note we don't currently support certificate_authorities nor
// signature_algorithms_cert, and don't check the algorithms of the
// signatures on the chain (which anyway are a SHOULD, see RFC 8446,
// Section 4.4.2.2).
config := chi.config
if config == nil {
config = &Config{}
}
vers, ok := config.mutualVersion(roleServer, chi.isQUIC, chi.SupportedVersions)
if !ok {
return errors.New("no mutually supported protocol versions")
}
// If the client specified the name they are trying to connect to, the
// certificate needs to be valid for it.
if chi.ServerName != "" {
x509Cert, err := c.leaf()
if err != nil {
return fmt.Errorf("failed to parse certificate: %w", err)
}
if err := x509Cert.VerifyHostname(chi.ServerName); err != nil {
return fmt.Errorf("certificate is not valid for requested server name: %w", err)
}
}
// supportsRSAFallback returns nil if the certificate and connection support
// the static RSA key exchange, and unsupported otherwise. The logic for
// supporting static RSA is completely disjoint from the logic for
// supporting signed key exchanges, so we just check it as a fallback.View on GitHub (pinned to b6b368adc5)
Solutions
- Align MinVersion/MaxVersion between client and server to a common range.
- Lower the server MinVersion (with a documented risk assessment) to overlap the client.
- Upgrade the client to a TLS stack that supports the server's minimum version.
- Use SupportsCertificate to choose a cert only after confirming mutual version support.
Example fix
// before srvCfg.MinVersion = tls.VersionTLS13 cliCfg.MaxVersion = tls.VersionTLS12 // no overlap // after srvCfg.MinVersion = tls.VersionTLS12 cliCfg.MaxVersion = tls.VersionTLS13 // overlap at TLS 1.2
Defensive patterns
Strategy: validation
Validate before calling
// Confirm a client/server version range overlaps before relying on a cert.
func versionsOverlap(clientMin, clientMax, serverMin, serverMax uint16) bool {
return clientMin <= serverMax && serverMin <= clientMax
}
// Or use chi.SupportsCertificate(cert) which returns this error when ranges are disjoint. Prevention
- Set explicit MinVersion/MaxVersion on both client and server and document the range.
- Before raising MinVersion, survey clients for version support.
- Treat SupportsCertificate errors as guidance for cert selection, not fatal.
- Log negotiated versions in staging to detect version skew early.
When it happens
Trigger: Calling chi.SupportsCertificate(cert) where chi.SupportedVersions and the server's MinVersion/MaxVersion are disjoint (e.g., client offers TLS 1.0-1.1 only, server requires TLS 1.3). Reached at the top of SupportsCertificate.
Common situations: Server set MinVersion=TLS1.3 but an old client only supports TLS 1.2; client restricted MaxVersion below the server minimum; version skew after a security hardening that raised MinVersion.
Related errors
- ECDSA verification failure
- Ed25519 verification failure
- tls: missing signature_algorithms from TLS 1.2 peer
- tls: peer doesn't support any of the certificate's signature
- tls: ML-DSA certificates require TLS 1.3
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/16ce9565d139310d.
Report an issue: GitHub.