golang/go · error
tls: client offered TLS version older than TLS 1.3
Error message
tls: client offered TLS version older than TLS 1.3
What it means
RFC 9001 §4.2 mandates QUIC use TLS 1.3 minimum; older TLS versions are forbidden in QUIC. If any entry in the QUIC ClientHello's supportedVersions is below VersionTLS13 (0x0304), the server sends protocol_version and aborts.
Source
Thrown at src/crypto/tls/handshake_server_tls13.go:272
hs.sharedKey, hs.hello.serverShare, err = ke.serverSharedSecret(c.config.rand(), clientKeyShare.data)
if err != nil {
c.sendAlert(alertIllegalParameter)
return errors.New("tls: invalid client key share")
}
selectedProto, err := negotiateALPN(c.config.NextProtos, hs.clientHello.alpnProtocols, c.quic != nil)
if err != nil {
c.sendAlert(alertNoApplicationProtocol)
return err
}
c.clientProtocol = selectedProto
if c.quic != nil {
// RFC 9001 Section 4.2: Clients MUST NOT offer TLS versions older than 1.3.
for _, v := range hs.clientHello.supportedVersions {
if v < VersionTLS13 {
c.sendAlert(alertProtocolVersion)
return errors.New("tls: client offered TLS version older than TLS 1.3")
}
}
// RFC 9001 Section 8.2.
if hs.clientHello.quicTransportParameters == nil {
c.sendAlert(alertMissingExtension)
return errors.New("tls: client did not send a quic_transport_parameters extension")
}
c.quicSetTransportParameters(hs.clientHello.quicTransportParameters)
} else {
if hs.clientHello.quicTransportParameters != nil {
c.sendAlert(alertUnsupportedExtension)
return errors.New("tls: client sent an unexpected quic_transport_parameters extension")
}
}
c.serverName = hs.clientHello.serverName
return nil
}View on GitHub (pinned to b6b368adc5)
Solutions
- Configure the QUIC client to advertise only TLS 1.3 (0x0304) in supported_versions
- Use a QUIC stack that conforms to RFC 9001 (do not mix TLS 1.2 code paths with QUIC)
Example fix
// before
supportedVersions = []uint16{0x0303, 0x0304}
// after
supportedVersions = []uint16{0x0304} Defensive patterns
Strategy: validation
Validate before calling
// QUIC client: ensure no TLS version below 1.3 is advertised.
for _, v := range supportedVersions {
if v < 0x0304 {
return fmt.Errorf("QUIC forbids TLS version 0x%04x", v)
}
} Try / catch
if err := tlsConn.Handshake(); err != nil {
if strings.Contains(err.Error(), "older than TLS 1.3") {
log.Printf("QUIC client advertised pre-1.3 from %v", remote)
}
c.Close()
return
} Prevention
- In QUIC, advertise only TLS 1.3 in supported_versions
- Use a QUIC stack that conforms to RFC 9001; never reuse a TLS 1.2 code path over QUIC
When it happens
Trigger: A QUIC handshake where the client includes TLS 1.2 (0x0303) or earlier in supportedVersions.
Common situations: A QUIC stack that incorrectly advertises TLS 1.2 compatibility; a TLS 1.2 client mistakenly run over a QUIC transport; QUIC/TLS interop bugs.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- tls: client did not send a quic_transport_parameters extensi
- tls: client sent an unexpected quic_transport_parameters ext
- tls: missing signature_algorithms from TLS 1.2 peer
- tls: peer doesn't support any of the certificate's signature
- tls: server sent unrequested session ticket
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/51e8a53fa22d941b.
Report an issue: GitHub.