golang/go · error
tls: server did not send a quic_transport_parameters extensi
Error message
tls: server did not send a quic_transport_parameters extension
What it means
QUIC-specific: RFC 9001 §8.2 mandates that a QUIC server's EncryptedExtensions carry the quic_transport_parameters extension. When the tls.Config is in QUIC mode (c.quic != nil) and the extension is absent, Go sends `missing_extension` and aborts. Indicates a QUIC server that did not echo transport parameters.
Source
Thrown at src/crypto/tls/handshake_client_tls13.go:551
c.sendAlert(alertUnexpectedMessage)
return unexpectedMessageError(encryptedExtensions, msg)
}
if err := checkALPN(hs.hello.alpnProtocols, encryptedExtensions.alpnProtocol, c.quic != nil); err != nil {
// RFC 8446 specifies that no_application_protocol is sent by servers, but
// does not specify how clients handle the selection of an incompatible protocol.
// RFC 9001 Section 8.1 specifies that QUIC clients send no_application_protocol
// in this case. Always sending no_application_protocol seems reasonable.
c.sendAlert(alertNoApplicationProtocol)
return err
}
c.clientProtocol = encryptedExtensions.alpnProtocol
if c.quic != nil {
if encryptedExtensions.quicTransportParameters == nil {
// RFC 9001 Section 8.2.
c.sendAlert(alertMissingExtension)
return errors.New("tls: server did not send a quic_transport_parameters extension")
}
c.quicSetTransportParameters(encryptedExtensions.quicTransportParameters)
} else {
if encryptedExtensions.quicTransportParameters != nil {
c.sendAlert(alertUnsupportedExtension)
return errors.New("tls: server sent an unexpected quic_transport_parameters extension")
}
}
if !hs.hello.earlyData && encryptedExtensions.earlyData {
c.sendAlert(alertUnsupportedExtension)
return errors.New("tls: server sent an unexpected early_data extension")
}
if hs.hello.earlyData && !encryptedExtensions.earlyData {
c.quicRejectedEarlyData()
}
if encryptedExtensions.earlyData {
if hs.session.cipherSuite != c.cipherSuite {View on GitHub (pinned to b6b368adc5)
Solutions
- Confirm the peer is actually a QUIC server, not a plain TLS-over-TCP server.
- Update the QUIC library (quic-go et al.) and the server to matching versions.
- Verify QUIC transport parameters are sent by the client too (QUIC requires both directions).
- Report the missing extension to the QUIC server implementer.
Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight: confirm this is genuinely a QUIC connection and your QUIC lib is wired up.
// QUIC mode is entered by the QUIC library; if c.quic == nil you are NOT in QUIC mode.
if !usingQUIC {
return errors.New("peer is a QUIC server; use a QUIC transport, not tls.Dial")
} Try / catch
// QUIC handshake errors surface from the QUIC library wrapping crypto/tls.
// Check your QUIC library's error type (e.g., quic-go ApplicationError/TransportError).
if err := qconn.Handshake(); err != nil {
var te *qerr.TransportError
if errors.As(err, &te) { /* inspect te.ErrorCode */ }
} Prevention
- Use a maintained QUIC library (e.g., quic-go) that correctly drives crypto/tls QUIC mode.
- Match client and server QUIC versions.
- Never feed a plain TCP connection into QUIC-configured tls.Config.
When it happens
Trigger: Calling tls.Config for a QUIC connection (config has QUIC transport parameters set via QUIC control-plane APIs) and the server's EncryptedExtensions omits quic_transport_parameters.
Common situations: QUIC server (HTTP/3, QUIC transport) that does not implement the TLS-QUIC integration correctly, version skew between the QUIC library and the server, or a server that is actually a plain TLS server reached over a QUIC tunnel.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- tls: server sent an unexpected quic_transport_parameters ext
- tls: server sent encrypted client hello retry configs after
- tls: server sent two HelloRetryRequest messages
- tls: server sent a cookie in a normal ServerHello
- tls: malformed key_share extension
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/00bfcc27573b2e69.
Report an issue: GitHub.