Fixing common SSL errors

The error codes browsers and command-line tools print, translated into the cause and the one change that usually fixes it.

Browsers and command-line tools report certificate problems as short codes that say almost nothing about the cause. Below, each code is paired with what it actually means and the one thing that usually fixes it. If you only have the domain name, start with the Domain SSL Checker — it names the failure before you go changing config.

The chain is broken

NET::ERR_CERT_AUTHORITY_INVALID · SEC_ERROR_UNKNOWN_ISSUER · curl (60) unable to get local issuer certificate · PKIX path building failed

The client cannot connect your certificate to a root it trusts. In practice this is almost always a missing intermediate: you installed the leaf certificate alone, and your own browser hides the mistake because it cached the intermediate from another site. Other people's browsers, curl, Java and mobile apps do not.

openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null | grep -c "BEGIN CERTIFICATE"

A result of 1 is the bug. You should see the leaf plus at least one intermediate.

The name does not match

NET::ERR_CERT_COMMON_NAME_INVALID · SSL_ERROR_BAD_CERT_DOMAIN · certificate is not valid for …

The hostname in the address bar is not in the certificate's SAN list. The Common Name field is ignored entirely by modern browsers, so a certificate that "has the right CN" still fails if the SAN list is missing that name.

How a client decides the certificate is for the wrong name Four hostnames are checked against the same certificate, whose SAN list holds example.com, www.example.com and star dot example.com. The first two match a name in the list exactly. api.example.com matches the wildcard, because it adds one label. shop.eu.example.com adds two labels, matches nothing, and the connection fails with ERR_CERT_COMMON_NAME_INVALID. what the visitor typed example.com www.example.com api.example.com shop.eu.example.com names in the certificate example.com www.example.com *.example.com one label only MATCHED — the connection proceeds NO MATCH — ERR_CERT_COMMON_NAME_INVALID two labels below the apex; the wildcard does not reach
The certificate never changes here — only the name being asked for. Three of these four hostnames are served by the same certificate, and the fourth needs its own name added to the SAN list, or a second wildcard for that level.
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -ext subjectAltName

The dates are wrong

NET::ERR_CERT_DATE_INVALID · SEC_ERROR_EXPIRED_CERTIFICATE · certificate has expired

Either the certificate really has expired, or the client's clock is off. Check which before touching the server — a device with a wrong date reports this on every HTTPS site, not just yours.

echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -dates

The handshake fails outright

ERR_SSL_PROTOCOL_ERROR · ERR_SSL_VERSION_OR_CIPHER_MISMATCH · SSL_ERROR_NO_CYPHER_OVERLAP

No certificate was ever examined — client and server could not agree on how to talk. The TLS Version Check shows which protocol versions the server actually accepts.

The server will not start

key values mismatch · SSL_CTX_use_PrivateKey_file failed · PEM routines: no start line

Config-time failures, before any client is involved. The first is the common one: the certificate and the private key are not a pair, usually because a second CSR was generated during a re-issue and the matching key was overwritten.

openssl x509 -in cert.pem -noout -pubkey | openssl sha256; openssl pkey -in example.com.key -pubout | openssl sha256

Two identical digests means they match. The Key Matcher does the same check in your browser.

The certificate is fine and it still looks wrong