golang/go · error
tls: server's certificate uses ML-DSA, which requires TLS 1.
Error message
tls: server's certificate uses ML-DSA, which requires TLS 1.3
What it means
Thrown in verifyServerCertificate() when the server's leaf certificate uses an ML-DSA (Module-Lattice-Based Digital Signature Algorithm) public key but the negotiated TLS version is below 1.3. ML-DSA is a post-quantum signature algorithm only defined for TLS 1.3 per the relevant specifications.
Source
Thrown at src/crypto/tls/handshake_client.go:1188
c.verifiedChains, err = fipsAllowedChains(chains)
if err != nil {
c.sendAlert(alertBadCertificate)
return &CertificateVerificationError{UnverifiedCertificates: certs, Err: err}
}
}
if fips140tls.Required() && !isCertificateAllowedFIPS(certs[0]) {
c.sendAlert(alertBadCertificate)
err := errors.New("server's certificate is not allowed in FIPS 140-3 mode")
return &CertificateVerificationError{UnverifiedCertificates: certs, Err: err}
}
switch certs[0].PublicKey.(type) {
case *rsa.PublicKey, *ecdsa.PublicKey, ed25519.PublicKey:
case *mldsa.PublicKey:
if c.vers < VersionTLS13 {
c.sendAlert(alertIllegalParameter)
return errors.New("tls: server's certificate uses ML-DSA, which requires TLS 1.3")
}
default:
c.sendAlert(alertUnsupportedCertificate)
return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey)
}
c.peerCertificates = certs
if c.config.VerifyPeerCertificate != nil && !echRejected {
if err := c.config.VerifyPeerCertificate(certificates, c.verifiedChains); err != nil {
c.sendAlert(alertBadCertificate)
return err
}
}
if c.config.VerifyConnection != nil && !echRejected {
if err := c.config.VerifyConnection(c.connectionStateLocked()); err != nil {
c.sendAlert(alertBadCertificate)View on GitHub (pinned to b6b368adc5)
Solutions
- Remove or raise the MaxVersion restriction in tls.Config to allow TLS 1.3 negotiation.
- Ensure MinVersion is not set above VersionTLS13 and MaxVersion defaults to VersionTLS13.
- If TLS 1.3 is unavailable on the client, replace the server certificate with a classical algorithm (RSA, ECDSA, or Ed25519).
- Verify TLS 1.3 support end-to-end: openssl s_client -connect host:443 -tls1_3
Example fix
// before — forces TLS 1.2, incompatible with ML-DSA certs
config := &tls.Config{
MaxVersion: tls.VersionTLS12,
}
// after — allow TLS 1.3
config := &tls.Config{
MinVersion: tls.VersionTLS12,
MaxVersion: tls.VersionTLS13,
} Defensive patterns
Strategy: validation
Validate before calling
// Validate TLS version config before connecting when ML-DSA certs may be used
func validateConfigForPostQuantum(config *tls.Config) error {
if config.MaxVersion != 0 && config.MaxVersion < tls.VersionTLS13 {
return fmt.Errorf("MaxVersion is below TLS 1.3; servers with ML-DSA certs will fail")
}
return nil
} Try / catch
conn, err := tls.Dial("tcp", addr, config)
if err != nil {
if strings.Contains(err.Error(), "ML-DSA, which requires TLS 1.3") {
// Raise MaxVersion to allow TLS 1.3 and retry
config.MaxVersion = tls.VersionTLS13
conn, err = tls.Dial("tcp", addr, config)
}
} Prevention
- Do not restrict MaxVersion below TLS 1.3 unless absolutely necessary.
- Test TLS version negotiation with: openssl s_client -connect host:443 -tls1_3.
- Document which servers use post-quantum certificates.
When it happens
Trigger: Triggered when certs[0].PublicKey is *mldsa.PublicKey and c.vers < VersionTLS13 (0x0304). The client sends alertIllegalParameter.
Common situations: Client tls.Config restricts MaxVersion to TLS 1.2 while connecting to a server with a post-quantum ML-DSA certificate. Client in a restricted environment that downgrades the TLS version. Server admin deployed ML-DSA certificates without ensuring all clients support TLS 1.3.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- tls: ML-DSA certificates require TLS 1.3
- tls: received empty certificates message
- tls: client certificate uses ML-DSA, which requires TLS 1.3
- tls: server selected ML-DSA with TLS version < 1.3
- tls: failed to parse certificate from server: {err}
AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12).
Data as JSON: /api/errors/76e59579dcc2049b.
Report an issue: GitHub.