golang/go · error
tls: MinVersion must be >= VersionTLS13 if EncryptedClientHe
Error message
tls: MinVersion must be >= VersionTLS13 if EncryptedClientHelloConfigList is populated
What it means
Thrown by makeClientHello when config.EncryptedClientHelloConfigList is non-nil (ECH is enabled on the client) AND config.MinVersion is explicitly set to a value below VersionTLS13 (0x0304). ECH is a TLS 1.3-only extension per RFC 9460, so requiring a minimum version below 1.3 while enabling ECH is contradictory and rejected at configuration time.
Source
Thrown at src/crypto/tls/handshake_client.go:177
hello.keyShares = hello.keyShares[:1]
}
}
if c.quic != nil {
p, err := c.quicGetTransportParameters()
if err != nil {
return nil, nil, nil, err
}
if p == nil {
p = []byte{}
}
hello.quicTransportParameters = p
}
var ech *echClientContext
if c.config.EncryptedClientHelloConfigList != nil {
if c.config.MinVersion != 0 && c.config.MinVersion < VersionTLS13 {
return nil, nil, nil, errors.New("tls: MinVersion must be >= VersionTLS13 if EncryptedClientHelloConfigList is populated")
}
if c.config.MaxVersion != 0 && c.config.MaxVersion <= VersionTLS12 {
return nil, nil, nil, errors.New("tls: MaxVersion must be >= VersionTLS13 if EncryptedClientHelloConfigList is populated")
}
echConfigs, err := parseECHConfigList(c.config.EncryptedClientHelloConfigList)
if err != nil {
return nil, nil, nil, err
}
echConfig, echPK, kdf, aead := pickECHConfig(echConfigs)
if echConfig == nil {
return nil, nil, nil, errors.New("tls: EncryptedClientHelloConfigList contains no valid configs")
}
ech = &echClientContext{config: echConfig, kdfID: kdf.ID(), aeadID: aead.ID()}
hello.encryptedClientHello = []byte{1} // indicate inner hello
// We need to explicitly set these 1.2 fields to nil, as we do not
// marshal them when encoding the inner hello, otherwise transcripts
// will later mismatch.
hello.supportedPoints = nilView on GitHub (pinned to b6b368adc5)
Solutions
- Set MinVersion to tls.VersionTLS13 (or higher) when using ECH
- Leave MinVersion as 0 (zero value) when using ECH — the zero value allows TLS 1.3 and the ECH code path works correctly
- If you need TLS 1.2 fallback, do not use ECH — ECH and TLS 1.2 are mutually exclusive
Example fix
// before
config := &tls.Config{
EncryptedClientHelloConfigList: echConfigList,
MinVersion: tls.VersionTLS12,
}
// after
config := &tls.Config{
EncryptedClientHelloConfigList: echConfigList,
MinVersion: tls.VersionTLS13,
} Defensive patterns
Strategy: validation
Validate before calling
func validateECHClientConfig(config *tls.Config) error {
if config.EncryptedClientHelloConfigList == nil {
return nil
}
if config.MinVersion != 0 && config.MinVersion < tls.VersionTLS13 {
return errors.New("MinVersion must be >= VersionTLS13 when ECH is enabled")
}
if config.MaxVersion != 0 && config.MaxVersion <= tls.VersionTLS12 {
return errors.New("MaxVersion must be >= VersionTLS13 when ECH is enabled")
}
return nil
} Try / catch
// Pre-validate before dial:
//
// if err := validateECHClientConfig(config); err != nil {
// log.Fatal(err)
// }
// conn, err := tls.Dial("tcp", addr, config) Prevention
- Always set MinVersion >= tls.VersionTLS13 when EncryptedClientHelloConfigList is populated
- Build a Config constructor that validates ECH + version constraints together
- Write unit tests asserting ECH-enabled configs reject TLS 1.2 MinVersion
When it happens
Trigger: Setting both EncryptedClientHelloConfigList (to a non-nil byte slice) and MinVersion to VersionTLS12 (0x0303), VersionTLS11 (0x0302), or VersionTLS10 (0x0301) simultaneously.
Common situations: Adding ECH to an existing tls.Config that had MinVersion=VersionTLS12 for legacy compatibility. Copying a production config that restricted MinVersion and adding ECH without updating the version floor. Misunderstanding that ECH requires TLS 1.3.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- tls: MaxVersion must be >= VersionTLS13 if EncryptedClientHe
- tls: client sent encrypted_client_hello extension with unsup
- tls: client sent encrypted_client_hello extension but did no
- tls: no supported versions satisfy MinVersion and MaxVersion
- tls: no supported key exchange methods (CurveIDs)
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/b2506cadea27771e.
Report an issue: GitHub.