Skip to content
ecdsa.com
Node.js tls.checkServerIdentity()Node.js crypto

Error message

Hostname/IP does not match certificate's altnames: Host: api.example.com. is not in the cert's altnames: DNS:www.example.com

Also printed as

  • Hostname/IP does not match certificate's altnames: IP: 127.0.0.1 is not in the cert's list:
  • code: 'ERR_TLS_CERT_ALTNAME_INVALID'
  • ERR_TLS_CERT_ALTNAME_INVALID

The host and the altnames list are filled in per failure. For IP addresses the wording is "Hostname/IP does not match certificate's altnames: IP: <address> is not in the cert's list: <entries>". npm shows it as "npm error code ERR_TLS_CERT_ALTNAME_INVALID".

Node.js tls.checkServerIdentity() — code ERR_TLS_CERT_ALTNAME_INVALID

What it means

The certificate chain is trusted, but tls.checkServerIdentity() found no Subject Alternative Name matching the host Node.js connected to. The message lists both sides: the host you asked for and the names the certificate actually carries, so the mismatch is visible at a glance. The Common Name is ignored when the certificate has a SAN extension.

Why it happens

How to fix it

  1. 1.

    List the certificate's names

    Compare subjectAltName with the host you connect to.

    bash
    echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \
      | openssl x509 -noout -ext subjectAltName
  2. 2.

    Reissue with every name in use

    Add all DNS names and, where clients connect by address, IP entries.

    bash
    openssl req -new -key server.key -out server.csr -subj "/CN=api.example.com" \
      -addext "subjectAltName=DNS:api.example.com,DNS:www.example.com,IP:10.0.0.5"
  3. 3.

    Set servername when connecting by address

    Keep the certificate's name in servername (and the Host header) and connect to the address; verification then uses the correct name instead of being switched off.

    js
    // Connect to an address but verify the certificate's real name (also sent as SNI)
    import https from "node:https";
    
    https.get({ host: "10.0.0.5", port: 443, path: "/", servername: "api.example.com",
                headers: { host: "api.example.com" } }, (res) => res.resume());
  4. 4.

    Narrow exception with checkServerIdentity

    For a legacy host whose certificate cannot be reissued yet, map one known alias to the certificate's name and delegate to tls.checkServerIdentity(). Never return undefined unconditionally: that disables the name check completely.

    js
    // Narrow exception for a host you cannot reissue: accept one extra name, keep all other checks
    import https from "node:https";
    import tls from "node:tls";
    
    const agent = new https.Agent({
      checkServerIdentity: (host, cert) =>
        tls.checkServerIdentity(host === "legacy-alias.internal" ? "api.example.com" : host, cert),
    });

Related errors

Browse the full signature error database