DEV Community

Merlonix
Merlonix

Posted on Originally published at merlonix.com

SSL Certificate Name Mismatch: NET::ERR_CERT_COMMON_NAME_INVALID

The certificate is real. It's signed by a genuine CA, it's nowhere near expiry, and the chain is complete. And the browser still slams the door:

Your connection is not private
NET::ERR_CERT_COMMON_NAME_INVALID
Enter fullscreen mode Exit fullscreen mode

Every stack says the same thing in its own accent. Chrome and Edge say NET::ERR_CERT_COMMON_NAME_INVALID. Firefox says SSL_ERROR_BAD_CERT_DOMAIN. curl says curl: (60) SSL: no alternative certificate subject name matches target host name. Node says ERR_TLS_CERT_ALTNAME_INVALIDHostname/IP does not match certificate's altnames. Python says ssl.CertificateError: hostname 'app.example.com' doesn't match 'example.com'. One root cause, six dialects: the certificate the server presented is not valid for the name you asked for.

This is a different failure from the two it's most often confused with. It is not an expired certificate (the dates are fine) and it is not a broken or incomplete chain (the path to a trusted root is intact). The cryptography is sound and the trust is real — it just vouches for a different hostname than the one on the connection.


The Common Name Stopped Counting in 2017

The error message is a fossil. It still says "common name," but the Common Name (CN) field — the human-readable Subject: CN=example.com on a certificate — has been ignored for hostname matching by every mainstream browser since around 2017 (Chrome 58 was the loud one). What actually gets checked now is the Subject Alternative Name (SAN) extension: a list of the exact hostnames the certificate is authorized for.

That means a certificate can carry CN=example.com, look correct to a human reading it, and still be rejected — because the SAN list doesn't include the host you connected to. The CN is decoration. The SAN is the contract. A modern client builds the SAN list, checks whether your hostname is in it (honoring a wildcard only as the entire leftmost label), and if it isn't, it stops. It does not fall back to the CN, and it does not care that the certificate is otherwise perfect.

So the question is never "is this a valid certificate?" It plainly is. The question is "does this certificate's SAN list cover this exact hostname?" — and when the answer is no, you get the name-mismatch error, no matter how healthy everything else looks.

What Actually Causes It

In rough order of how often they bite:

  • The apex/www split. The single most common trigger. A certificate is issued for example.com but not www.example.com (or the reverse), and a request lands on the uncovered name — often because a redirect, a hardcoded link, or a stray DNS record sends traffic to the host the cert doesn't list. The fix is to issue for both names (SAN = example.com and www.example.com) or to redirect at a layer that terminates TLS with the right cert first.

  • Wildcard depth. *.example.com covers exactly one label: it matches api.example.com and www.example.com, but not foo.bar.example.com (two labels deep) and not the bare apex example.com (zero labels). A wildcard is not "everything under the domain" — it's "exactly one label here." A new sub-subdomain, or serving the apex off a wildcard-only cert, produces a mismatch that the wildcard looks like it should have covered.

  • A default or fallback certificate. The server received a request for a hostname it has no vhost or SNI match for, so it answered with whatever certificate is configured as the default — frequently the cert for a different site on the same box, a shared-hosting placeholder, or a load balancer's own name. The client gets a valid certificate for the wrong identity. Common on shared hosting, misconfigured reverse proxies, and CDNs where the custom hostname was added to DNS before it was added to the TLS config.

  • CN-only, no SAN at all. An older or hand-rolled certificate (or one from an internal CA) issued with a Common Name but no SAN extension. It named exactly one host the legacy way — and since every modern client ignores the CN, it matches nothing. This looks especially baffling because the CN is right there, spelling out the hostname, and the client refuses anyway.

  • An IP address against a name certificate. Connecting to https://203.0.113.10 when the certificate lists DNS names, not that IP as an iPAddress SAN. Browsers and clients require the literal IP in the SAN to accept an IP connection; a name-only cert can't cover it.

Only the last two are about how the certificate was issued; the first three are about a request reaching a host the (correct) certificate simply wasn't meant to serve. Both feel identical from the browser — a valid cert, wrong name — which is why reading the actual SAN list is the only way to tell them apart.

How to See the Names Your Server Actually Presents

Stop reading the CN and read the SAN. One command pulls the certificate the server serves for a given SNI hostname and prints its names:

openssl s_client -connect example.com:443 -servername www.example.com </dev/null 2>/dev/null \
  | openssl x509 -noout -subject -ext subjectAltName
Enter fullscreen mode Exit fullscreen mode

Two things to read:

  • X509v3 Subject Alternative Name. This is the authoritative list. Every hostname the certificate is valid for is here (DNS:example.com, DNS:www.example.com). If the name you're connecting to — the -servername you passed — is not in this list, and no wildcard entry covers it as a single leftmost label, that is your mismatch, confirmed. The subject= line (the CN) is only there to show you how misleading it can be: it can name your host perfectly while the SAN omits it.

  • The -servername matters. On a server hosting multiple names behind SNI, the certificate you get back depends on the name you send. Run the command once with -servername www.example.com and once with -servername example.com; if you get different certificates — or the same one that only covers one of them — you've found an apex/www or a default-cert problem directly. curl -v https://host shows the same information inline if you'd rather read it there.

The tell that distinguishes this from every other TLS error: the certificate openssl prints is unexpired and chains cleanly, and the only thing wrong is that your hostname isn't in the SAN list. When that's the case, no amount of reissuing for validity or fixing the chain helps — the certificate has to actually name the host you're serving it on.

What This Means If You Operate the Server

  • Issue for every name you answer on. If both example.com and www.example.com reach your server over TLS, the certificate's SAN must list both — or the uncovered one must be redirected at a tier that terminates TLS correctly before the request ever reaches the mismatched cert. "We only use www" is only true if nothing ever hits the apex, and something always does.

  • Know your wildcard's exact reach. Before you launch metrics.internal.example.com behind a *.example.com cert, remember the wildcard covers one label, not the whole subtree. Deep subdomains and the bare apex each need their own SAN entry (or their own certificate).

  • Check what SNI actually returns, per name. A default-certificate mismatch is invisible until you request the specific hostname. After any change to vhosts, custom hostnames, or a CDN's TLS config, probe each name with its own -servername from outside the box.

  • Watch the SAN list, not just the expiry date. A certificate can be renewed on schedule, pass every expiry alert, and still stop covering a hostname the day someone re-issued it from a template that dropped a SAN. Monitoring that only reads notAfter will call that certificate healthy while a real fraction of your traffic gets NET::ERR_CERT_COMMON_NAME_INVALID.

What This Means If You Consume One

  • Don't disable verification to route around it. curl -k, rejectUnauthorized: false, or a blanket "trust all hosts" turns off the exact check that just told you the endpoint's identity doesn't match its name — which is precisely the signal you want left on when a request could be silently reaching the wrong host.

  • Confirm you're calling the name the cert covers. Sometimes the mismatch is on your side: you're hitting api.example.com when the documented, certificate-covered endpoint is example.com/api. The SAN list tells you the names the server is prepared to be, and pointing your client at one of those is the fix.

  • If it's a third party, the report writes itself. "Your endpoint serves a certificate whose SAN list is example.com but I'm connecting to www.example.comopenssl s_client confirms the name isn't covered" is a precise, actionable bug for them to fix, and far better than working around it with verification turned off.


A name-mismatch error is the browser refusing to accept a real certificate for the wrong identity — and it is right to. The certificate is valid; it just belongs to a different name than the one on the wire. The trap is that it looks like a certificate problem you can fix by reissuing or by fixing the chain, when the actual repair is making the certificate's SAN list and the hostnames you serve agree with each other.

Merlonix reads the certificate your server actually presents — the SAN list included — from outside your stack, and tells you in plain language when the names it covers stop matching the host it's serving, naming the exact hostnames the certificate is valid for so you can see the gap. You can check a domain's live certificate and DNS right now without signing up, watch a certificate's expiry with the free cert watcher, and the free tools hub has the rest. For the two failures this one gets confused with, why a certificate that works in your browser fails in curl covers the chain case, and what happens when an SSL certificate expires covers the date case.

The browser answers "is this a valid certificate for the name I typed?" — and when it says no on a certificate that is otherwise perfect, it isn't being difficult. It's telling you the certificate and the hostname have quietly stopped agreeing, and the only place to fix that is where they're supposed to match: the SAN list your server hands out.

Top comments (0)