How to Debug SSL Handshake Failures: A Practical Guide

SSL handshake failures can have many causes. This guide covers the most common errors, how to diagnose them with OpenSSL, and how to fix them.

When a TLS handshake fails, the error message is often cryptic. This guide covers the most common handshake failures and the tools to diagnose them systematically.

Your Primary Diagnostic Tool: openssl s_client

The fastest way to inspect what a server is presenting:

openssl s_client -connect example.com:443 -servername example.com

This shows you the certificate chain, the TLS version negotiated, the cipher suite chosen, and any verification errors — all in one output.

Common Handshake Failures

SSL_ERROR_BAD_CERT_DOMAIN / ERR_CERT_COMMON_NAME_INVALID

The domain you're connecting to isn't covered by the certificate's Subject Alternative Names. See our guide on hostname mismatch errors.

CERTIFICATE_VERIFY_FAILED (unable to get local issuer certificate)

The certificate chain is incomplete — the server isn't sending an intermediate certificate. Fix: install the full chain (leaf + all intermediates) on the server. See missing intermediate certificate.

CERTIFICATE_VERIFY_FAILED (certificate has expired)

The certificate's Not After date has passed. Check the expiry with: openssl s_client -connect example.com:443 | openssl x509 -noout -dates. See certificate expired errors.

ERR_CERT_AUTHORITY_INVALID / UNABLE_TO_VERIFY_LEAF_SIGNATURE

The root CA isn't in the connecting client's trust store. This is common with self-signed certificates or internal private CAs — you need to add the root to the client's trust store. See untrusted root certificate.

Handshake Failure: No Shared Cipher

The client and server couldn't agree on a cipher suite. This usually means the server is configured too restrictively (e.g., TLS 1.3 only) or the client is too old. Check your server's TLS configuration and ensure TLS 1.2 with modern cipher suites is still enabled as a fallback.

Decoding the Certificate from the Handshake

You can extract the certificate from a live connection and decode it:

openssl s_client -connect example.com:443 </dev/null 2>/dev/null \
  | openssl x509 -text

Or copy the PEM output directly into the SSL Certificate Decoder for a structured view of every field.

Decode any SSL certificate instantly

Paste any PEM certificate into the free decoder — see subject, issuer, SANs, fingerprints, validity dates, and all X.509 extensions explained in plain English.

Open the Decoder