go-sql-driver/mysql · error
TLS requested but server does not support TLS
Error message
TLS requested but server does not support TLS
What it means
ErrNoTLS is returned during the handshake (packets.go:223) when the client configured TLS (cfg.TLS != nil) but the server's advertised capability flags do not include clientSSL. The driver refuses to silently downgrade to plaintext unless allowFallbackToPlaintext is set, to avoid leaking credentials.
Solutions
- Enable SSL on the server (mysqld --ssl, provide cert/key) so it advertises the SSL capability.
- If plaintext is acceptable for this hop, add allowFallbackToPlaintext=true to the DSN so the driver downgrades instead of erroring.
- If neither is possible, remove the tls parameter and accept a plaintext connection deliberately.
- Verify you are reaching the real MySQL port and not a proxy that mangles capabilities.
Example fix
// before dsn := "user:pass@tcp(10.0.0.5:3306)/db?tls=true" // -> ErrNoTLS on a server without SSL // after (option A): let the driver fall back to plaintext safely dsn := "user:pass@tcp(10.0.0.5:3306)/db?tls=true&allowFallbackToPlaintext=true" // after (option B): enable SSL on mysqld and keep tls=true
Defensive patterns
Strategy: validation
Validate before calling
// Build the DSN with a deliberate fallback so a non-TLS server does not // hard-fail, while still preferring TLS. dsn := "user:pass@tcp(host:3306)/db?tls=true&allowFallbackToPlaintext=true"
Type guard
func isNoTLS(err error) bool {
return errors.Is(err, mysql.ErrNoTLS)
} Try / catch
db, err := sql.Open("mysql", dsn)
if err == nil {
err = db.PingContext(ctx)
}
if errors.Is(err, mysql.ErrNoTLS) {
// either enable SSL on the server or consciously allow plaintext
return decideTLSFallback()
} Prevention
- Confirm the server advertises SSL (SHOW VARIABLES LIKE 'have_ssl') before requiring TLS.
- Add allowFallbackToPlaintext=true only when a plaintext hop is acceptable.
- Register TLS configs once at startup with mysql.RegisterTLSConfig.
- Treat a sudden ErrNoTLS as a possible misrouted DSN (wrong host/proxy).
When it happens
Trigger: Opening a connection with a DSN containing tls=true / tls=skip-verify / a named TLS config against a mysqld started without SSL support, a server whose SSL library was compiled out, or a port-forwarded/proxied endpoint that strips the SSL capability bit.
Common situations: Local dev mysqld built without OpenSSL; connecting through a sidecar/proxy that terminates the protocol; test containers started with --skip-ssl; security policy requires TLS but the target cannot provide it.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- invalid value for server pub key name
- invalid value for TLS config name
- key ' ' is reserved
- unexpected resp from server for caching_sha2_password…
- invalid max_allowed_packet value
AI-assisted analysis of go-sql-driver/mysql@03d76c7e07 (2026-08-07).
Data as JSON: /api/errors/0e697cb5172f730d.
Report an issue: GitHub.
Appendix: source
Thrown at errors.go:21
// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package mysql
import (
"errors"
"fmt"
"log"
"os"
)
// Various errors the driver might return. Can change between driver versions.
var (
ErrInvalidConn = errors.New("invalid connection")
ErrMalformPkt = errors.New("malformed packet")
ErrNoTLS = errors.New("TLS requested but server does not support TLS")
ErrCleartextPassword = errors.New("this user requires clear text authentication. If you still want to use it, please add 'allowCleartextPasswords=1' to your DSN")
ErrNativePassword = errors.New("this user requires mysql native password authentication")
ErrOldPassword = errors.New("this user requires old password authentication. If you still want to use it, please add 'allowOldPasswords=1' to your DSN. See also https://github.com/go-sql-driver/mysql/wiki/old_passwords")
ErrUnknownPlugin = errors.New("this authentication plugin is not supported")
ErrOldProtocol = errors.New("MySQL server does not support required protocol 41+")
ErrPktSync = errors.New("commands out of sync. You can't run this command now")
ErrPktSyncMul = errors.New("commands out of sync. Did you run multiple statements at once?")
ErrPktTooLarge = errors.New("packet for query is too large. Try adjusting the `Config.MaxAllowedPacket`")
ErrBusyBuffer = errors.New("busy buffer")
// errBadConnNoWrite is used for connection errors where nothing was sent to the database yet.
// If this happens first in a function starting a database interaction, it should be replaced by driver.ErrBadConn
// to trigger a resend. Use mc.markBadConn(err) to do this.
// See https://github.com/go-sql-driver/mysql/pull/302
errBadConnNoWrite = errors.New("bad connection")
)
View on GitHub (pinned to 03d76c7e07)