What the error actually says
NET::ERR_CERT_COMMON_NAME_INVALID reports a mismatch between the name you visited and the certificate the server sent. It does not establish that the certificate is otherwise valid: check the issuer, expiry and chain as well. A certificate can have more than one problem.
The error’s name is a leftover. Browsers used to compare the address against the certificate’s Common Name (CN). Since Chrome 58 (2017) they only look at the Subject Alternative Name (SAN) list, as RFC 2818 had recommended since 2000. Firefox shows the same failure as SSL_ERROR_BAD_CERT_DOMAIN, and Safari as “This certificate is not valid (host name mismatch)”.
So the whole diagnosis comes down to two questions:
- Which name exactly is the browser connecting to? (
www.example.comandexample.comare different names.) - Which names are on the certificate that actually comes back for that name?
Step 1: read the SAN list the server is really sending
Don’t trust the certificate files on your server or in your CDN dashboard. Read what goes out on the wire, for the exact name that fails:
openssl s_client -connect www.example.com:443 -servername www.example.com </dev/null 2>/dev/null \
| openssl x509 -noout -subject -issuer -ext subjectAltName
-servername matters. It sends SNI, the “which site do you want” hint a browser sends. Without it, many servers return their default certificate, and you end up debugging the wrong one.
In Chrome: click “Not secure” → “Certificate is not valid” → Details → Subject Alternative Name.
The SSL check shows the SAN list and the issuer for any hostname, from outside your network.
Compare the SAN list with the name in the address bar, character by character. In practice the mismatch is almost always one of the cases below.
The usual causes
1. www and the apex aren’t both on the certificate
The certificate covers example.com, and someone visits www.example.com, or the other way round. One way this happens is requesting the certificate with only one -d flag.
Fix: reissue the certificate with both names. With certbot:
certbot --expand -d example.com -d www.example.com
If you don’t want to serve both, still keep both names on the certificate and redirect one to the other. The redirect only happens after TLS succeeds, so the name being redirected away from needs a valid certificate too.
2. A wildcard that doesn’t reach
*.example.com covers www.example.com and shop.example.com. It does not cover example.com itself, and it does not cover dev.shop.example.com. Each * stands for exactly one label.
Fix: add the apex explicitly (most CAs, including Let’s Encrypt, let you put example.com and *.example.com on one certificate). For deeper names, add *.shop.example.com or the specific hostnames.
This bites Cloudflare users regularly. The free Universal SSL certificate covers example.com and *.example.com, so a proxied record like dev.shop.example.com gets this exact error. You either need an Advanced Certificate that includes that level, or you set the record to DNS-only and let the origin present its own certificate.
3. The name points at a server that has never heard of it
The DNS record points at a server, and that server has no site configured for this name. It answers with whatever certificate is its default: the hosting company’s own, the first virtual host alphabetically, or a placeholder.
Typical moments:
- You changed DNS to a new host but haven’t added the domain in the new host’s panel yet.
- A shared IP whose virtual host configuration lists
example.combut notwww.example.com. - nginx with no
server_namematch falls back to the firstserverblock for that port.
Check where the name resolves with a DNS lookup. Then look at the issuer in step 1. If the certificate belongs to a different company or a different customer’s site, this is your case.
Fix: add the hostname to the site’s configuration on that server (server_name, ServerAlias, the “custom domains” list in a panel) and issue a certificate for it.
4. A CNAME to a SaaS that wasn’t told about your domain
docs.example.com is a CNAME to yourname.github.io, something.herokuapp.com, a Shopify store, a Vercel or Netlify project. The platform’s edge answers with the certificate for its own domain (*.github.io) because you never registered docs.example.com as a custom domain on the platform side.
Fix: add the custom domain in the platform’s settings and wait for it to issue a certificate. Most platforms need the DNS record in place first, then take a few minutes to issue.
5. Visiting by IP address or an internal name
https://203.0.113.10 or https://intranet will fail against a certificate for example.com. Public CAs no longer issue certificates for internal names or reserved IP ranges at all. That has been a CA/Browser Forum rule since 2015.
Fix: use the real hostname. For internal services, use a name under a domain you own (intranet.corp.example.com) and either a public certificate for that name or an internal CA your devices trust. For local development, mkcert creates a locally trusted certificate for localhost and custom names.
6. Something on the user’s network is answering instead of you
If the error shows up only on one Wi-Fi, one office, or one laptop, and the certificate’s issuer is a company you don’t recognise, the culprit is between the user and you:
- Captive portals (hotels, airports) intercept the first HTTPS request before you log in.
- Corporate TLS-inspection proxies re-sign traffic. Normally their root is installed on company devices; on a personal device it isn’t.
- Antivirus “HTTPS scanning” does the same on one machine.
Your server is fine in this case. Compare by running the SSL check from outside, which doesn’t go through the user’s network.
7. An old answer still cached somewhere
You moved the site and the new server has the right certificate, but some users still get the old server, which has none for this name. TTLs, ISP resolvers and the OS cache can keep the old IP for hours, or longer if the old TTL was long.
Run a propagation check to see whether public resolvers still return the old address. Keep the old server answering with a valid certificate until they all agree.
After the fix
- Re-test every name people actually use: apex,
www, and any subdomain in links or emails. Each one is a separate check. - If you reissued, confirm the server is serving the new certificate and not a cached old one. Reload nginx or Apache, and check the CDN has picked it up.
- If a renewal job created this problem, check its domain list. Automated renewals reuse the names from the first request, so a name added to the site later never makes it onto the certificate.
Related errors that look similar
NET::ERR_CERT_DATE_INVALID: right name, but expired or not yet valid. Often a wrong clock on the device.NET::ERR_CERT_AUTHORITY_INVALID: the name may be right, but the issuer isn’t trusted: a self-signed certificate, or a missing intermediate.ERR_SSL_VERSION_OR_CIPHER_MISMATCH: the TLS handshake fails before any certificate is compared. On CDNs this often means no certificate exists for that name at all.
Check your own domain now
Free, no sign-up. Runs the exact check this guide describes and shows what to fix.