{"record":{"id":"0e697cb5172f730d","repo":"go-sql-driver/mysql","slug":"tls-requested-but-server-does-not-support-tls","errorCode":null,"errorMessage":"TLS requested but server does not support TLS","messagePattern":"TLS requested but server does not support TLS","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"errors.go","lineNumber":21,"sourceCode":"// Copyright 2013 The Go-MySQL-Driver Authors. All rights reserved.\n//\n// This Source Code Form is subject to the terms of the Mozilla Public\n// License, v. 2.0. If a copy of the MPL was not distributed with this file,\n// You can obtain one at http://mozilla.org/MPL/2.0/.\n\npackage mysql\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n)\n\n// Various errors the driver might return. Can change between driver versions.\nvar (\n\tErrInvalidConn       = errors.New(\"invalid connection\")\n\tErrMalformPkt        = errors.New(\"malformed packet\")\n\tErrNoTLS             = errors.New(\"TLS requested but server does not support TLS\")\n\tErrCleartextPassword = errors.New(\"this user requires clear text authentication. If you still want to use it, please add 'allowCleartextPasswords=1' to your DSN\")\n\tErrNativePassword    = errors.New(\"this user requires mysql native password authentication\")\n\tErrOldPassword       = 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\")\n\tErrUnknownPlugin     = errors.New(\"this authentication plugin is not supported\")\n\tErrOldProtocol       = errors.New(\"MySQL server does not support required protocol 41+\")\n\tErrPktSync           = errors.New(\"commands out of sync. You can't run this command now\")\n\tErrPktSyncMul        = errors.New(\"commands out of sync. Did you run multiple statements at once?\")\n\tErrPktTooLarge       = errors.New(\"packet for query is too large. Try adjusting the `Config.MaxAllowedPacket`\")\n\tErrBusyBuffer        = errors.New(\"busy buffer\")\n\n\t// errBadConnNoWrite is used for connection errors where nothing was sent to the database yet.\n\t// If this happens first in a function starting a database interaction, it should be replaced by driver.ErrBadConn\n\t// to trigger a resend. Use mc.markBadConn(err) to do this.\n\t// See https://github.com/go-sql-driver/mysql/pull/302\n\terrBadConnNoWrite = errors.New(\"bad connection\")\n)\n","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/go-sql-driver/mysql/blob/03d76c7e07908e255ce62d126d07ede3f2365d86/errors.go#L3-L39","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ndsn := \"user:pass@tcp(10.0.0.5:3306)/db?tls=true\"\n// -> ErrNoTLS on a server without SSL\n\n// after (option A): let the driver fall back to plaintext safely\ndsn := \"user:pass@tcp(10.0.0.5:3306)/db?tls=true&allowFallbackToPlaintext=true\"\n// after (option B): enable SSL on mysqld and keep tls=true","handlingStrategy":"validation","validationCode":"// Build the DSN with a deliberate fallback so a non-TLS server does not\n// hard-fail, while still preferring TLS.\ndsn := \"user:pass@tcp(host:3306)/db?tls=true&allowFallbackToPlaintext=true\"","typeGuard":"func isNoTLS(err error) bool {\n    return errors.Is(err, mysql.ErrNoTLS)\n}","tryCatchPattern":"db, err := sql.Open(\"mysql\", dsn)\nif err == nil {\n    err = db.PingContext(ctx)\n}\nif errors.Is(err, mysql.ErrNoTLS) {\n    // either enable SSL on the server or consciously allow plaintext\n    return decideTLSFallback()\n}","preventionTips":["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)."],"tags":["tls","security","handshake"],"backgroundTag":null,"analyzedSha":"03d76c7e07908e255ce62d126d07ede3f2365d86","analyzedAt":"2026-08-07T10:39:17.340Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}