Skip to content
ecdsa.com
npm (Node.js)Package managers

Error message

npm error code UNABLE_TO_VERIFY_LEAF_SIGNATURE

Also printed as

  • npm ERR! code UNABLE_TO_VERIFY_LEAF_SIGNATURE
  • npm error request to https://registry.example.com/lodash failed, reason: unable to verify the first certificate

npm 10 and later print "npm error code UNABLE_TO_VERIFY_LEAF_SIGNATURE"; npm 9 and older "npm ERR! code UNABLE_TO_VERIFY_LEAF_SIGNATURE". Recent Node.js versions add "; if the root CA is installed locally, try running Node.js with --use-system-ca" to the reason line.

npm (Node.js) — registry request over HTTPS

What it means

The registry (or a proxy in front of it) sent only its own certificate, and Node.js could not find the certificate that issued it. Without the issuer, the leaf's signature cannot be checked at all. This is a server configuration problem: the intermediate certificate is missing from the handshake, which Node.js does not repair by downloading it.

Why it happens

How to fix it

  1. 1.

    Count the certificates in the handshake

    Only depth 0 with an intermediate as issuer confirms the missing intermediate.

    bash
    openssl s_client -connect registry.example.com:443 -servername registry.example.com -showcerts </dev/null 2>/dev/null \
      | grep -E '^ *[0-9]+ s:|^ *i:'
  2. 2.

    Serve the full chain on the registry

    Configure the TLS terminator in front of the registry with leaf plus intermediates. This fixes npm, yarn, pnpm, Docker and every other client at once.

    text
    # Registry behind nginx: serve leaf + intermediate(s)
    ssl_certificate     /etc/nginx/tls/registry.example.com.fullchain.pem;
    ssl_certificate_key /etc/nginx/tls/registry.example.com.key;
  3. 3.

    Workaround: trust the intermediate on the client

    A cafile with the intermediate and its root lets npm verify the leaf until the server is fixed; cafile replaces the default roots for npm, so add public roots too if the same npm also uses registry.npmjs.org.

    bash
    # Until the registry is fixed: trust the intermediate (plus its root) on the client
    cat issuing-ca.pem corp-root-ca.pem > /etc/ssl/private-ca/registry-ca.pem
    npm config set cafile /etc/ssl/private-ca/registry-ca.pem

Related errors

Browse the full signature error database