SSL_ERROR_BAD_CERT_DOMAIN and ERR_CERT_COMMON_NAME_INVALID: the certificate is for another name.

Firefox says SSL_ERROR_BAD_CERT_DOMAIN, Chrome says NET::ERR_CERT_COMMON_NAME_INVALID, curl says no alternative subject name matches. All three mean the same thing: the certificate the server sent does not list the name you asked for. The work is finding out whether the server sent the wrong certificate or the right certificate is missing a name.

Written by · Published 2026-09-30 · 7 min read

What the error says

During the handshake the client checks that the name in the address bar appears in the certificate's Subject Alternative Name (SAN) list. If it does not, every client refuses the connection, and each words it differently:

ClientError
Chrome, EdgeNET::ERR_CERT_COMMON_NAME_INVALID
FirefoxSSL_ERROR_BAD_CERT_DOMAIN
curlSSL: no alternative certificate subject name matches target host name
PythonCERTIFICATE_VERIFY_FAILED ... Hostname mismatch, certificate is not valid for
Node.jsERR_TLS_CERT_ALTNAME_INVALID
Gox509: certificate is valid for a.example, not b.example
JavaNo subject alternative DNS name matching example.com found

Chrome's name is a leftover. It says "common name", but Chrome has ignored the common name since 2017 and only reads the SAN list. That matters for one of the causes below.

Prove which case you have

Put the name into the SSL/TLS certificate checker. It connects with that name as SNI and shows the certificate the server actually returned: its subject, every SAN, and whether the name matched. Then read the SAN list.

From a shell, the same comparison with and without SNI shows whether the server picks a certificate by name at all:

openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -ext subjectAltName
openssl s_client -connect example.com:443 -noservername </dev/null 2>/dev/null | openssl x509 -noout -subject -ext subjectAltName

If the first is right and the second is not, the server is fine for modern clients and the failing client is not sending SNI.

Cause 1: the server sent its default certificate

A server hosting several names picks the certificate from the name the client sends in SNI. When nothing matches, it falls back to a default, and that default is for some other site. In practice this is almost always one of:

Cause 2: the certificate does not cover the name

The server sent your certificate, and it simply does not list the name. Usually it is one of these rules:

Cause 3: a certificate with only a common name

Certificates from internal CAs, old appliances and hand-rolled openssl req commands sometimes put the hostname only in the subject's CN and have no SAN extension. Chrome (since version 58), Go (since 1.15), current Python and most other clients no longer look at the CN, so the name is simply not there as far as they are concerned. The fix is to reissue with a SAN. For an internal CA:

openssl req -new -key server.key -subj "/CN=intranet.example.com" \
  -addext "subjectAltName=DNS:intranet.example.com" -out server.csr

Then check that the CA's signing profile copies the extension across; some do not by default.

Cause 4: a client that does not send SNI

Very old clients (Java 6, Python 2 before 2.7.9, Android 2, Windows XP) connect without SNI, so a multi-site server can only give them its default. There is nothing to fix on the certificate. Either make this site the default for the address, give it an address of its own, or accept that such clients cannot reach it.

What not to do

Turning off hostname checking (curl -k, verify=False, check_hostname = False) makes the error disappear by accepting any valid certificate for any site, including one an attacker bought for their own domain. It is how interception works. Fix the name on the server; once the checker shows a match for every address, every client agrees.

All guides · All tools