Troubleshooting guide · dns-ssl · Published 2026-08-16 · 3 min read

TLS handshake failures troubleshooting

Troubleshoot TLS handshake failures by layer: protocol, cipher, certificate, and server configuration, with browser and log evidence.

Read the symptom before touching anything

A TLS handshake failure is any error between the moment the browser chooses the address and the moment encrypted bytes start flowing. The browser text already partitions the cause space:

SymptomLayer the error lives in
ERR_SSL_PROTOCOL_ERROR (Chrome) / SSL_ERROR_PROTOCOL_VERSION_ALERT (Firefox)Protocol version mismatch
ERR_SSL_VERSION_OR_CIPHER_MISMATCH / ssl_error_no_cypher_overlapCipher suite overlap
SSL_ERROR_SSL with a certificate warningCertificate/trust chain
Handshake that hangs and then timeoutNetwork path (or server overloaded)

The same failure can be told apart in one sentence: protocol errors say "we do not share a TLS version", cipher errors say "we do not share a cipher", certificate errors say "we share a cipher but the identity does not check out", and timeouts say "neither side showed up on time".

Diagnosis by layer

1. Protocol version

Check which TLS versions the server actually speaks:

openssl s_client -connect example.com:443 -tls1_2

If the server only exposes TLS 1.0 or 1.1 (or rejects -tls1_2), every modern browser fails at handshake because it offers no shared version. The fix lives in the web server TLS config, which is covered in the SSL error and the handshake basics articles.

2. Cipher suite

When the version works but ciphers do not, the server advertised suites the client cannot use (for example, only suites restricted by export-grade policy). List the server's offered ciphers:

openssl s_client -connect example.com:443

Enable a modern common suite (TLS_AES_256_GCM_SHA384 and friends) and remove the legacy set. If the server is behind Cloudflare, see the Cloudflare 525 article, which is the same mismatch from the edge side.

3. Certificate

Read the served certificate and chain:

openssl s_client -connect example.com:443 -showcerts

Check the three failure classes: expiry (covered by the certificate errors article), missing intermediate chain (chain incomplete, the peer cannot validate), and hostname mismatch (certificate valid but for another name, common after a domain change).

4. Server overload

A TLS timeout with no error text, coinciding with load, is the MySQL-gone-away equivalent at the socket layer: the origin trims keepalive connections the CDN relies on. Check connection limits (netstat/ss on the server after reproducing on :443 only), and consult the timeout article for the session trimming fixes that also stop handshake timeouts.

Involved fixes (when the log is authoritative)

When the browser text is ambiguous, read the server log line that records the alert. nginx writes SSL_do_handshake() failed, which names the exact alert code; ssl_errors from the daemon line up with the ciphers/version test above. If the error appears for some visitors and not others, it usually points at clients stuck on an old OS or Java runtime, not at the server.

When to involve a professional

You have largely solved it when the three tests above pinpoint a layer. There are two cases worth hiring out: a corporate reverse-proxy chain (load balancer, WAF, CDN, and origin each hold a handshake hop, and the failing hop is invisible mid-chain), and a certificate chain that resists repair because the origin refuses to bundle intermediates. On Cloudflare the edge shows the chain problem before origin traffic, so the 525 article is the quicker route there.

Need a website built, fixed, optimised, migrated or replaced?

This technical resource is written by CSMBAC, a small design and development studio. If you would rather hand the problem to a professional, the website service page explains how we build enquiry-ready websites.

Explore website services