How to Fix MySQL Error 2026: SSL Connection Error

ERROR 2026 (HY000): SSL connection error: <detail> is raised when the TLS/SSL handshake between the MySQL client and server cannot be completed. The error symbol is CR_SSL_CONNECTION_ERROR.

Impact

This is a client-side connection error, meaning the connection is rejected before any query is executed. No transaction is started, no SQL reaches the server, and the application receives a fatal connection failure. Because it occurs at the transport layer, the error appears before any ORM or query builder has a chance to act.

In application frameworks, this surfaces as an unhandled connection exception at startup or at the point where a connection pool is first populated. In Java (JDBC/Connector/J), it typically throws CommunicationsException wrapping an SSLHandshakeException. In Python (mysql-connector-python or PyMySQL), it raises mysql.connector.errors.InterfaceError or OperationalError with the underlying SSL detail appended to the message. In Node.js (mysql2), the connection emits an ECONNRESET or SSL_ERROR event.

Common Causes

  1. Expired or not-yet-valid certificate — The server's TLS certificate has passed its notAfter date, or the client certificate is outside its validity window. MySQL validates certificate dates during the handshake.

  2. CA certificate mismatch — The client is configured to verify the server's certificate (--ssl-verify-server-cert or ssl_verify_server_cert=1) but the CA bundle provided does not include the issuing CA for the server cert. This is common when using self-signed certs or private PKI.

  3. Hostname / CN mismatch — Certificate verification is enabled and the server certificate's CN or Subject Alternative Names (SANs) do not match the hostname used in the connection string.

  4. Incompatible TLS protocol versions — The client requires TLS 1.2 but the server only offers TLS 1.3 (or vice versa), or one side has disabled a protocol version that the other side requires. MySQL 8.0.28+ defaults to tls_version=TLSv1.2,TLSv1.3; TLS 1.0 and 1.1 are removed.

  5. Incompatible cipher suites — The client and server have no overlapping cipher suite in common, so the handshake cannot negotiate encryption parameters.

  6. Client configured to require SSL but server has SSL disabled — The client connection uses --ssl-mode=REQUIRED or the driver's ssl=true, but the server was started without SSL support (have_ssl = DISABLED).

  7. Corrupted or wrong-format key/certificate files — A PEM file was accidentally truncated, stored in DER format, or the private key does not match the certificate.

Troubleshooting and Resolution Steps

  1. Check whether the server has SSL enabled:

    SHOW VARIABLES LIKE 'have_ssl';
    SHOW VARIABLES LIKE 'have_openssl';
    

    If the result is DISABLED, the server was compiled or started without TLS support. Either restart with --ssl-ca, --ssl-cert, and --ssl-key pointing to valid files, or use a distribution that includes OpenSSL support.

  2. Inspect the server's TLS configuration:

    SHOW VARIABLES LIKE 'tls_version';
    SHOW VARIABLES LIKE 'ssl_%';
    

    Note the ssl_ca, ssl_cert, and ssl_key paths. Verify the files exist and are readable by the MySQL process.

  3. Check certificate validity dates from the shell:

    openssl x509 -in /var/lib/mysql/server-cert.pem -noout -dates
    

    If notAfter is in the past, regenerate the certificate or renew it via your CA. For self-signed certs, re-run mysql_ssl_rsa_setup or generate manually:

    mysql_ssl_rsa_setup --datadir=/var/lib/mysql
    
  4. Verify the CA chain and hostname match:

    openssl verify -CAfile /path/to/ca-cert.pem /path/to/server-cert.pem
    openssl x509 -in /path/to/server-cert.pem -noout -subject -ext subjectAltName
    

    The CN or a SAN entry must match the hostname your client uses. If you connect to 127.0.0.1 but the cert only covers localhost (or the FQDN), either add a SAN or disable hostname verification on the client (--ssl-mode=VERIFY_CA instead of VERIFY_IDENTITY).

  5. Test the TLS handshake directly with openssl:

    openssl s_client -connect host:3306 -starttls mysql -CAfile /path/to/ca-cert.pem
    

    The output shows the negotiated protocol, cipher, and any certificate errors without involving the MySQL client.

  6. Check and align TLS versions:

    -- On the server, restrict or expand allowed versions:
    SET GLOBAL tls_version = 'TLSv1.2,TLSv1.3';
    ALTER INSTANCE RELOAD TLS;  -- applies without restart (MySQL 8.0+)
    

    On the client side, pass --tls-version=TLSv1.2 (CLI) or set tls_versions in your connector configuration.

  7. Temporarily skip certificate verification to isolate the issue:

    mysql -h host -u user -p --ssl-mode=REQUIRED --ssl-ca='' 2>/dev/null
    # or
    mysql -h host -u user -p --ssl-mode=PREFERRED
    

    If this succeeds, the problem is certificate-related rather than a protocol mismatch. Do not leave verification disabled in production.

Additional Information

  • Error 2026 is a client-side error in the CR_ (Client Result) range. It is distinct from server-side SSL errors reported in the MySQL error log.
  • The trailing detail in the message (e.g., SSL connection error: error:14090086:SSL routines:ssl3_get_server_certificate:certificate verify failed) is the raw OpenSSL error string and usually pinpoints the exact cause.
  • In MySQL 8.0, ALTER INSTANCE RELOAD TLS allows replacing certificates at runtime without a server restart.
  • --ssl-mode accepts DISABLED, PREFERRED, REQUIRED, VERIFY_CA, and VERIFY_IDENTITY. The default in MySQL 8.0 clients is PREFERRED; many cloud providers enforce REQUIRED or VERIFY_CA.
  • AWS RDS, Google Cloud SQL, and Azure Database for MySQL each ship their own CA bundles. Download the correct bundle from your cloud provider rather than using the system CA store.
  • Related errors: CR_SSL_CONNECTION_ERROR (2026) is sometimes accompanied by server-side ER_ACCESS_DENIED_ERROR (1045) if the user account requires REQUIRE SSL and the connection falls back to plaintext.

Frequently Asked Questions

Why does MySQL 2026 happen only after a cert renewal? After renewing a certificate, the new cert's CA chain or SANs sometimes differ from the old one. If the client was configured with a pinned CA (--ssl-ca) and the new cert was issued by a different intermediate CA, the trust chain breaks. Re-export and redistribute the new CA bundle to all clients and reload the TLS configuration on the server with ALTER INSTANCE RELOAD TLS.

Can I connect without SSL to work around this temporarily? Yes, if the server allows non-SSL connections: use --ssl-mode=DISABLED in the CLI or set ssl=false in your driver. However, user accounts configured with REQUIRE SSL will still reject the connection with error 1045. For production databases that store sensitive data, bypassing SSL is not recommended.

Why does this error appear in Docker or CI environments? Containerized MySQL setups often generate self-signed certificates at first startup, but automated clients running in a different container may use a system CA store that does not include those self-signed CAs. Either mount the generated ca-cert.pem into the client container, or configure the client with --ssl-mode=REQUIRED (without CA verification) if certificate identity validation is not needed in that environment.

How do I confirm the TLS handshake is working after a fix? Connect with the mysql CLI and run:

\s
-- or
SHOW STATUS LIKE 'Ssl_cipher';

A non-empty Ssl_cipher value confirms that the current session is encrypted. SHOW SESSION STATUS LIKE 'Ssl_version' shows the negotiated protocol version.

Subscribe to the Pulse Newsletter

Get early access to new Pulse features, insightful blogs & exclusive events , webinars, and workshops.

We use cookies to provide an optimized user experience and understand our traffic. To learn more, read our use of cookies; otherwise, please choose 'Accept Cookies' to continue using our website.