- Node.js
- Exact text checked with the real tool
ERR_TLS_CERT_ALTNAME_INVALID
Also seen in: npm, yarn, axios, fetch (undici), Electron
In one sentence
The certificate is trusted, but the hostname or IP address you connected to is not among the names in its Subject Alternative Name list.
Where you see it
In Node.js HTTPS clients (https, fetch, axios, got) and in npm, after the certificate chain was accepted. The code is listed in the Node.js errors documentation; the check is done by tls.checkServerIdentity().
TypeError: fetch failed
...
[cause]: Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match certificate's altnames: Host: api.internal.example.com. is not in the cert's altnames: DNS:www.example.com
...
code: 'ERR_TLS_CERT_ALTNAME_INVALID',
reason: "Host: api.internal.example.com. is not in the cert's altnames: DNS:www.example.com",
host: 'api.internal.example.com',
When you connect by IP address and the certificate has no IP entries, the message ends differently:
Hostname/IP does not match certificate's altnames: IP: 10.0.0.5 is not in the cert's list:
npm shows the same code: npm error code ERR_TLS_CERT_ALTNAME_INVALID.
What it means
A certificate lists the names it is valid for in its Subject Alternative Name (SAN) extension. Node.js compares the host you connected to with that list. The message shows both sides: your host after Host: and the certificate’s names after altnames:. The certificate is genuine but issued for other names, so Node.js refuses it.
Likely causes
You use a name the certificate does not list
A short internal name, a load balancer’s DNS name, a container name such as api in Docker Compose, or localhost. The message already shows the certificate’s names; to see the full certificate:
openssl s_client -connect api.internal.example.com:443 -servername api.internal.example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -ext subjectAltName
Fix: use one of the listed names in your URL, or have the certificate reissued with every name clients use. For a private CA, put all names in the request:
openssl req -new -key server.key -subj "/CN=api.internal.example.com" \
-addext "subjectAltName=DNS:api.internal.example.com,DNS:api" -out server.csr
You connect by IP address
An IP address only matches an IP Address: entry in the SAN list. Use the DNS name, or reissue the certificate with an IP: entry. If you must connect to an IP but verify a name, set servername and keep the check:
https.get({ host: '10.0.0.5', servername: 'api.internal.example.com', path: '/' })
Node.js then sends api.internal.example.com in SNI and checks the certificate against that name.
The server sends the wrong certificate
A server with several sites chooses the certificate by the name in SNI and falls back to a default one. If the altnames in the message belong to a different site, the server is not configured for your name. Compare:
openssl s_client -connect api.internal.example.com:443 -servername api.internal.example.com </dev/null 2>/dev/null | openssl x509 -noout -ext subjectAltName
Add a matching server_name block in nginx, a ServerName virtual host in Apache, or a hostname binding in IIS, each with the right certificate. On Kubernetes, check that the Ingress tls.hosts list contains the name.
A wildcard does not cover this name
*.example.com matches exactly one label. It does not match example.com or v2.api.example.com. Add those names as separate SAN entries.
The certificate has no DNS name in its SAN
If the reason reads Host: api.internal.example.com. is not cert's CN: www.example.com, the certificate has no DNS name in its SAN list (no SAN at all, or only IP addresses), so Node.js fell back to the Common Name. Browsers and Go never do that. Reissue the certificate with every hostname as a DNS entry in the SAN list.
Check yours
Paste the server’s certificate and type the hostname from your URL. The matcher shows which SAN entries match and why the others do not.
Learn why
- Names and jobs: SANs, wildcards, key usage and the CA flag
- The TLS 1.3 handshake: where SNI fits.
- Related: Hostname mismatch in Python, SSL_ERROR_BAD_CERT_DOMAIN in Firefox.
Early edition. Checked against the standards; an independent expert review is in progress. Found a mistake? Tell us.