Browser SSL errors are unhelpful by design. They are written for end users, not for engineers, and they collapse a wide range of underlying issues into a small number of generic strings. Here is what they actually mean and the one-liner that will tell you for sure.
NET::ERR_CERT_DATE_INVALID
One of two things:
- The certificate is past its
notAfterdate (expired). - The client's system clock is wrong. The cert is valid; the device thinks it is 2019 because the CMOS battery died.
Check:
openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -dates
notBefore=Apr 12 00:00:00 2026 GMT
notAfter=Jul 11 23:59:59 2026 GMT
If the dates bracket today's date and you're still seeing the error on one specific machine, it's the device clock.
NET::ERR_CERT_COMMON_NAME_INVALID / SSL_ERROR_BAD_CERT_DOMAIN
The certificate is presented for one name; you connected to a different name. Almost always one of:
- You connected by IP instead of by hostname. Cert is for
example.com, you typedhttps://93.184.216.34. No SAN covers an IP. - You connected to
www.example.combut the cert only coversexample.com(or vice versa). Modern certs usually include both, but old ones don't. - SNI mismatch. The server presented a default cert because the client did not send an SNI extension — older Java versions, very old curl, anything using SSL 3.0 / TLS 1.0.
Check:
openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -ext subjectAltName
That lists every name covered by the cert. If the hostname you connected to is not in the list, the error is genuine.
NET::ERR_CERT_AUTHORITY_INVALID
The validator could not chain the leaf to a trusted root. Three causes:
- Missing intermediate. Server sent only the leaf. Verify with
openssl s_client ... -showcerts— count theBEGIN CERTIFICATEblocks. You should see at least two (leaf + intermediate). If you only see one, fix the server config (usefullchain.pem, notcert.pem). - Self-signed cert. Internal services often run with self-signed certs. The leaf is the root, and no client has it in their trust store. Either issue a real cert or distribute the self-signed cert to clients.
- Outdated trust store. Old Android, old corporate proxy, old curl in a stripped Docker image. Update the CA bundle: on Debian/Ubuntu
update-ca-certificates; in alpine imagesapk add ca-certificates.
NET::ERR_CERT_REVOKED
The CA has revoked the cert and the browser successfully fetched the revocation status (CRL or OCSP). Cause: a previous issuance was compromised or the domain owner requested revocation. Not a configuration error you can fix without re-issuing.
SSL_ERROR_NO_CYPHER_OVERLAP / ERR_SSL_VERSION_OR_CIPHER_MISMATCH
The client and the server have no protocol or cipher suite in common. Two scenarios:
- Very old client trying to reach a modern server that no longer supports TLS 1.0/1.1. Upgrade the client.
- Modern client trying to reach an ancient server stuck on SSLv3. Upgrade the server.
Confirm what the server actually offers:
nmap --script ssl-enum-ciphers -p 443 example.com
Or use the per-protocol matrix on dnscheck — every probe runs four handshakes (TLS 1.0, 1.1, 1.2, 1.3) and reports which succeeded.
NET::ERR_CERT_WEAK_SIGNATURE_ALGORITHM
Cert is signed with SHA-1 (deprecated since 2017) or MD5 (deprecated since forever). Re-issue with a SHA-256 signing CA. If you cannot — because the issuing CA itself signs with SHA-1 — you need a different CA.
ERR_SSL_PROTOCOL_ERROR
The TLS layer received bytes it could not parse. Causes, roughly:
- Something is intercepting traffic on port 443 and returning HTTP instead of TLS (proxy misconfiguration, redirect loop, captive portal).
- An old middlebox is rewriting the handshake and breaking it.
- A bug in a specific TLS implementation.
The fastest test:
curl -vk https://example.com 2>&1 | head -30
Read the verbose output for the actual exchange.
NET::ERR_CERT_NON_UNIQUE_NAME
You requested a cert for a hostname whose name is not unique on the internet (typically an internal name like intranet or server.local). Public CAs cannot issue for non-unique names since 2015. You need an internal CA.
One generic workflow
When in doubt:
curl -vI https://example.comto see the raw handshake.openssl s_client -connect example.com:443 -servername example.com -showcertsto see what the server actually sends.- Open dnscheck and run the host to see chain + protocols + headers in one view.