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, e.g. tls=true/skip-verify/custom) but the server's capability flags do not include clientSSL, meaning the server does not support TLS — and the DSN did not set allowFallbackToPlaintext. This prevents silently downgrading an encrypted connection to plaintext.
Source
Thrown at errors.go:22
//
// 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")
)
var defaultLogger = Logger(log.New(os.Stderr, "[mysql] ", log.Ldate|log.Ltime))View on GitHub (pinned to c426bd9379)
Solutions
- Enable TLS on the MySQL server: provision certs and start mysqld with --ssl, or set require_secure_transport appropriately.
- If plaintext is acceptable on this link, add `allowFallbackToPlaintext=true` to the DSN so the driver drops TLS instead of erroring.
- Verify you are connecting to the intended host/port and that no intermediary strips the SSL capability.
Example fix
// before dsn := "u:p@tcp(host:3306)/db?tls=true" // after (option A: enable server TLS, keep dsn) // OR option B: explicitly allow plaintext fallback dsn := "u:p@tcp(host:3306)/db?tls=true&allowFallbackToPlaintext=true"
Defensive patterns
Strategy: fallback
Validate before calling
tlsOK, _ := strconv.ParseBool(os.Getenv("MYSQL_TLS"))
if !tlsOK {
// do not request TLS
} else {
dsn += "&allowFallbackToPlaintext=true"
} Try / catch
err := ping()
if errors.Is(err, mysql.ErrNoTLS) {
if allowPlaintext {
dsn += "&allowFallbackToPlaintext=true" // retry path
}
} Prevention
- Enable TLS on the server before requiring it in clients.
- Use allowFallbackToPlaintext only when plaintext is acceptable.
- Smoke-test the handshake against the exact server/port.
When it happens
Trigger: Connecting with `?tls=true` (or a registered TLS config) to a MySQL server started without SSL support (mysqld compiled/started without TLS, or ssl disabled). packets.go:219-224 checks capabilities & clientSSL == 0 and, unless AllowFallbackToPlaintext is true, returns ErrNoTLS.
Common situations: Pointing a TLS-configured client at a dev MySQL that has no certificates; server that supports TLS but the specific listener/account/port does not; misconfigured ProxySQL/intermediary that strips the SSL capability bit.
Related errors
- invalid DSN: interpolateParams can not be used with unsafe c
- invalid value / unknown config name: {cfg.TLSConfig}
- invalid bool value: {value}
- invalid value for server pub key name: %v
- invalid value for TLS config name: %v
AI-assisted analysis of go-sql-driver/mysql@c426bd9379 (2026-08-04).
Data as JSON: /data/errors/0e697cb5172f730d.json.
Report an issue: GitHub.