Node.js "unable to verify the first certificate" - Fix Incomplete Chains
By Daniel Zoghalchali·Latchkey
Node could not build a complete trust chain because the server did not send its intermediate certificate. Unlike a self-signed CA, the root is trusted - the chain just has a gap that the server (or your config) must fill.
What this error means
An HTTPS request or npm install fails with unable to verify the first certificate (UNABLE_TO_VERIFY_LEAF_SIGNATURE). It often appears against a private registry or proxy whose server is misconfigured to omit the intermediate.
npm / Node output
npm error code UNABLE_TO_VERIFY_LEAF_SIGNATURE
npm error request to https://registry.internal/... failed,
reason: unable to verify the first certificate
Diagnose it: which registry, and with what credentials?
Registry errors are resolved in a precedence chain, and the effective value is rarely the one in the file you are looking at. Scoped registries, .npmrc files at several levels, and environment variables all combine before a request is made.
Terminal
# the effective, fully merged configuration
npm config list -l | grep -E "registry|_auth|always-auth"
# where each value came from
npm config get registry
npm config get @yourscope:registry
# prove the token works, independently of the install
curl -sI -H "Authorization: Bearer $NPM_TOKEN" \
"$(npm config get registry)@yourscope%2fpackage" | head -1
Common causes
Server sends an incomplete certificate chain
The TLS server presents its leaf certificate but omits the intermediate CA that links it to a trusted root. Node cannot complete the chain, so verification fails.
The intermediate is not in the runner’s trust store
When the server will not send the intermediate, the client must already have it. A minimal runner image without that intermediate cannot verify the leaf.
How to fix it
Fix the server to send the full chain
The proper fix is server-side: configure the registry/proxy to present leaf + intermediate(s). Verify what it actually sends.
Terminal
# inspect the chain the server presents
openssl s_client -connect registry.internal:443 -showcerts
Supply the intermediate to the client
If you cannot change the server, provide the missing intermediate (and root) to Node and npm as an extra CA file.
Terminal
export NODE_EXTRA_CA_CERTS=/etc/ssl/certs/intermediate-bundle.pem
npm config set cafile /etc/ssl/certs/intermediate-bundle.pem
npm ci
How to prevent it
Configure TLS servers to present the full chain (leaf + intermediates).
Bundle required intermediates into runner images via NODE_EXTRA_CA_CERTS.
Test the chain with openssl s_client -showcerts when adding a new private host.
Frequently asked questions
What causes Node.js "unable to verify the first certificate"?
There are 2 common causes: server sends an incomplete certificate chain and the intermediate is not in the runner’s trust store. The TLS server presents its leaf certificate but omits the intermediate CA that links it to a trusted root.
How do I fix Node.js "unable to verify the first certificate"?
There are 2 fixes depending on which cause you have: fix the server to send the full chain and supply the intermediate to the client. Work through them in order, since the first is the most common.
What does Node.js "unable to verify the first certificate" actually mean?
An HTTPS request or npm install fails with unable to verify the first certificate (UNABLE_TO_VERIFY_LEAF_SIGNATURE).
How do I stop Node.js "unable to verify the first certificate" happening again?
Configure TLS servers to present the full chain (leaf + intermediates). The prevention section lists 3 changes that keep it from recurring.
Can Latchkey fix this automatically?
Yes. Latchkey runs your GitHub Actions on managed runners that detect this failure, apply the fix, and retry the job automatically - self-healing is on by default.
This is a transient network failure, not a bug in your code. Latchkey detects, repairs, and retries it for you.Start free →30-day trial · No credit card
Cookie Preferences
Choose which categories of cookies you want to allow. Essential cookies are always active as they are required for the site to function.
Essential
Required for the site to function.
Functional
Remembers your preferences like selected organization and dashboard settings.
Analytics
Helps us understand how the site is used (Google Analytics).