Reading SSL certificate errors: the four most common ones, decoded
ERR_CERT_AUTHORITY_INVALID. NET::ERR_CERT_DATE_INVALID. ERR_CERT_COMMON_NAME_INVALID. ERR_SSL_VERSION_OR_CIPHER_MISMATCH. The browser tells you almost exactly what's wrong if you know how to read it. Here is what each one means, why it happens, and what to do.
Browsers refuse to load a page over HTTPS for one of four reasons, almost every time. The error code in the URL bar tells you which one. Read the code and you've narrowed the cause from "the internet is broken" to one of "the certificate is wrong" / "the clock is wrong" / "the domain is wrong" / "the cryptography is wrong." Each of those has a small set of root causes and a known fix.
This post unpacks the four most common errors you'll see in Chrome, Edge, Firefox, and Safari — the underlying cause, the fastest diagnostic, and the fix. It's the field guide we wish we'd had the first time a customer reported a "scary red page."
1. ERR_CERT_AUTHORITY_INVALID (Chrome / Edge) · SEC_ERROR_UNKNOWN_ISSUER (Firefox)
The browser fetched a certificate but cannot trace it back to a root certificate authority it trusts. The chain of trust is broken somewhere between the leaf certificate (your domain) and a root in the browser's trust store.
Why this happens
In order of frequency:
- Missing intermediate certificate. This is the most common cause. The server presents only the leaf certificate, not the full chain — but the browser needs the intermediate(s) to bridge from leaf to root. Some browsers fetch missing intermediates via AIA (Authority Information Access) URLs; others do not. The site works in Chrome, fails in Firefox, and you're left chasing inconsistent reports.
- Self-signed certificate. You generated the certificate yourself; no public CA signed it. Common in development and on internal IPs.
- Private internal CA. Your organisation runs its own CA. Devices that have the root installed see the site as trusted; devices that don't see the error. Personal devices brought into the office often hit this when accessing internal resources.
- Expired or revoked root. Rarer. Affects ancient root certificates that have been removed from browser trust stores. AddTrust External CA Root expired in May 2020 and caused a famous wave of breakages.
Fast diagnostic
$ If the output shows only one subject= / issuer= pair, the server is presenting only the leaf. The intermediates are missing.
The Website Down Checker renders the whole chain and flags missing intermediates in the SSL panel.
Fix
- Missing intermediate. Concatenate the full chain into the certificate file your web server reads. Let's Encrypt provides this as
fullchain.pem(use that, notcert.pem). For other CAs the bundle name varies. Test with SSL Labs — it explicitly grades chain completeness. - Self-signed cert. Replace it with one signed by a public CA. Let's Encrypt is free and well-supported.
- Private internal CA. Distribute the root certificate to every device that needs access. For BYOD, this typically means MDM-managed installation.
2. NET::ERR_CERT_DATE_INVALID · SEC_ERROR_EXPIRED_CERTIFICATE
The certificate is outside its valid date range. Either it has expired, or — more rarely — the current time is before the certificate's notBefore date.
Why this happens
- Renewal forgotten. Public CAs issue 13-month or 90-day certs (Let's Encrypt issues 90 days, most paid CAs 13 months). Renewal is supposed to be automated; when it isn't, the cert expires silently.
- Auto-renewal silently broken. Certbot can't bind to port 80 because something else is using it. The DNS-01 challenge fails because the API key rotated. The renewal cron is on a server that has been decommissioned.
- Client clock wrong. The device showing the error has its clock set to the past or far future. Less common than it used to be but still happens on freshly-imaged devices, virtual machines that haven't synced NTP, embedded devices.
- Cert installed before its
notBefore. The CA issued a certificate with anotBeforedate in the future and the server picked it up immediately. Rare. Indicates a clock skew on the CA's side.
Fast diagnostic
$ Compare notBefore and notAfter against the current UTC time. If notAfter is in the past, the cert is expired. If notBefore is in the future, the cert isn't yet valid.
Fix
- Expired cert with working renewal infra: trigger manual renewal (
certbot renew --force-renewal). Investigate why the cron didn't fire. - Expired cert with broken renewal: fix the renewal pipeline before anything else. A manual renewal buys you 90 days but doesn't fix the underlying problem.
- Client clock wrong: the user's device, not the server. Time sync is the fix.
- Don't catch this manually. Set up monitoring. Domain Status Analyzer flags soon-to-expire certificates as part of its lifecycle output; SSL Labs sends free email warnings 30 days before expiry.
3. NET::ERR_CERT_COMMON_NAME_INVALID · SSL_ERROR_BAD_CERT_DOMAIN
The certificate is valid, dated correctly, and traces to a trusted root — but it isn't for the domain you're visiting.
Why this happens
- Wrong SNI selection. Multiple HTTPS sites share an IP. Your server picks the wrong certificate when responding because the Server Name Indication header isn't routed correctly. Visiting
example.comreturns the cert forother-customer.example. - Apex vs www mismatch. The cert covers
www.example.combut the user typedexample.com. (Or vice versa.) Most modern CAs include both via SAN entries; older issuance sometimes did not. - Wildcard cert with mismatched depth. A wildcard like
*.example.comcoversapi.example.combut NOTv2.api.example.com— wildcards match exactly one label. - Cert for a different brand entirely. You're behind a CDN that has misrouted SSL termination. The certificate it serves is for some other tenant.
Fast diagnostic
$ Compare the SAN list against the hostname you visited. If your hostname isn't covered, the cert is wrong for this domain.
Fix
- Reissue the certificate with the correct SAN entries.
- Or: fix the SNI routing on the server / CDN so the right cert is served for this hostname.
- For "apex vs www" specifically: issue a single cert that covers both, or maintain two separate certs with each pointing at the right vhost.
4. ERR_SSL_VERSION_OR_CIPHER_MISMATCH · SSL_ERROR_NO_CYPHER_OVERLAP
The client and server tried to negotiate a TLS connection and couldn't agree on a cipher suite or protocol version both sides support.
Why this happens
- Server disabled all the ciphers the client supports. Often happens when a sysadmin "hardens" the server config to TLS 1.3-only and an older client tries to connect. Browsers from before 2018 generally don't speak 1.3.
- Server still serving TLS 1.0 / 1.1 only. The reverse: an older server that hasn't been updated. Modern browsers refuse to negotiate 1.0/1.1 since 2020.
- Mismatched curve / signature algorithm. An ECDSA-only server faced with an RSA-only client. Almost never happens with modern setups.
- Misconfigured intermediate. The server is presenting a certificate whose signature algorithm isn't supported in TLS 1.3 (e.g. SHA-1). Rare.
Fast diagnostic
$ If neither version produces a handshake, the server is wedged. If only one version works, you've found the constraint.
Fix
- Server-side: enable both TLS 1.2 and 1.3. Don't go 1.3-only unless you've explicitly opted into that risk and audited your client base.
- Run SSL Labs — it reports the full negotiated cipher matrix and flags weak / disabled ciphers explicitly.
The two-minute SSL health check
Whenever a site reports an SSL error, run this loop on a known-good machine:
$ That single command answers:
- Does the server respond at all? (If not — it's a network / port issue, not an SSL one.)
- What's the certificate's
notBeforeandnotAfter? (Expired? Not yet valid?) - What's the subject (CN)? Does it match the hostname?
- What's the issuer? Is it a recognised CA?
- What other names does the cert cover via SAN?
Five questions, one command. Most SSL bugs resolve here.
Lesser-seen errors worth knowing
A few errors appear less often but are worth recognising on sight.
The error code reference at /error/[code] has a more complete catalogue if you encounter something not covered above.
A note about HSTS
If a site has previously sent an HSTS header and the browser has it cached, any certificate error becomes hard-fail with no "proceed anyway" option. This is intentional — HSTS is supposed to prevent downgrade attacks. But it does mean that if you accidentally publish HSTS on a site that isn't ready to support it permanently, you've locked yourself out for the duration of the HSTS max-age (commonly six months to two years).
The fix is to wait out the max-age. There is no way to remotely revoke an HSTS pin in a user's browser short of them manually clearing the HSTS storage.
Frequently asked
The certificate looks fine to me but my visitors keep reporting errors. What's happening?
Most likely a mismatch in trust stores. Your machine trusts a root that other machines don't — or has an intermediate cached that other machines don't have. Use SSL Labs — it tests from a fresh trust store and tells you exactly what a clean browser would experience.
Does Let's Encrypt's 90-day cert mean I have to manually renew every 90 days?
No — Let's Encrypt is specifically designed for automated renewal. The 90-day window is short on purpose: forces you to set up automation, which means certificates are always close to current. Use certbot or any of the ACME clients (acme.sh, lego, Caddy's built-in client). Auto-renewal targets 60 days by default, so you have a 30-day grace window if automation fails once.
Can I use a self-signed certificate for an internal API?
Technically yes, but treat it as friction. Every client needs the cert installed in its trust store. Switching to Let's Encrypt — even for internal services — is usually less work than maintaining an internal CA. If you genuinely need an internal CA (regulated industry, air-gapped network), document the root distribution process carefully and put renewal of the root itself on a calendar.
Is `https://` always more secure than `http://`?
HTTPS proves three things: encryption (eavesdroppers can't read traffic), integrity (no in-flight tampering), and authentication (you're talking to who you think you're talking to). It does NOT prove the site is well-built, the data behind the green padlock is safe, or that the operator is honest. A phishing site can have a perfectly valid Let's Encrypt cert. HTTPS is necessary, not sufficient.
The single best habit
Set a calendar reminder 30 days before any cert you care about expires. Better: deploy monitoring that pages you. The cost of an unexpected outage from an expired cert is always higher than the cost of the monitoring you needed.
For one-off checks: the Website Down Checker reports the full SSL state for any URL including chain validity, expiry dates, and the negotiated cipher. For continuous monitoring: a cron-driven openssl x509 -checkend over your important domains, piped to whichever alerting system you already run, is fifteen minutes of work.
On this page20
- 1. ERR_CERT_AUTHORITY_INVALID (Chrome / Edge) · SEC_ERROR_UNKNOWN_ISSUER (Firefox)
- Why this happens
- Fast diagnostic
- Fix
- 2. NET::ERR_CERT_DATE_INVALID · SEC_ERROR_EXPIRED_CERTIFICATE
- Why this happens
- Fast diagnostic
- Fix
- 3. NET::ERR_CERT_COMMON_NAME_INVALID · SSL_ERROR_BAD_CERT_DOMAIN
- Why this happens
- Fast diagnostic
- Fix
- 4. ERR_SSL_VERSION_OR_CIPHER_MISMATCH · SSL_ERROR_NO_CYPHER_OVERLAP
- Why this happens
- Fast diagnostic
- Fix
- The two-minute SSL health check
- Lesser-seen errors worth knowing
- A note about HSTS
- The single best habit