<!-- https://pkizerotohero.com/errors/npm-unable-to-get-issuer-cert-locally/ | Markdown mirror of the HTML page | PKI Zero to Hero, by Duyutech BV -->

> Fix npm UNABLE_TO_GET_ISSUER_CERT_LOCALLY on company networks and private registries: trust the right root with NODE_EXTRA_CA_CERTS, not strict-ssl false.

Source: https://pkizerotohero.com/errors/npm-unable-to-get-issuer-cert-locally/ · Last reviewed: 2026-10-20

- npm
- Exact text checked with the real tool

# UNABLE\_TO\_GET\_ISSUER\_CERT\_LOCALLY

Also seen in: Node.js, yarn, pnpm, fetch (undici), axios

**In one sentence:**

npm (Node.js) reached a CA certificate whose issuing root it does not have: usually a TLS-inspection proxy or company CA root, or a cafile setting that replaced the public roots.

[Check yours: Chain checker](https://pkizerotohero.com/tools/chain/)

## Where you see it

In `npm install`, `npm ci`, `npm view` and `npx`, and in any Node.js HTTPS client. npm prints the Node.js error code and the OpenSSL reason:

```text
$ npm install
npm error code UNABLE_TO_GET_ISSUER_CERT_LOCALLY
npm error errno UNABLE_TO_GET_ISSUER_CERT_LOCALLY
npm error request to https://registry.npmjs.org/express failed, reason: unable to get local issuer certificate
npm error A complete log of this run can be found in: /home/dev/.npm/_logs/2026-10-20T09_15_02_311Z-debug-0.log
```

Older npm versions print `npm ERR!` instead of `npm error`. In Node.js code the same problem appears as `code: 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY'`.

## What it means

The server’s [certificate chain](https://pkizerotohero.com/handbook/glossary/#certificate-chain) must end at a [root certificate](https://pkizerotohero.com/handbook/glossary/#root-certificate) that Node.js trusts. npm received the server’s certificate and at least one CA certificate, but could not find the root that issued the top one in its [trust store](https://pkizerotohero.com/handbook/glossary/#trust-store). Node.js uses its own bundled list of public roots by default, not the operating system’s, so a root IT installed on your computer can still be missing for npm.

## Likely causes

### A TLS-inspection proxy re-signs your traffic

The most common cause on company networks. The proxy decrypts HTTPS and re-signs it with its own CA. Check who issued the registry’s certificate:

```bash
openssl s_client -connect registry.npmjs.org:443 -servername registry.npmjs.org </dev/null 2>/dev/null | openssl x509 -noout -issuer
```

A public registry certificate comes from a public CA. If the issuer names your company or a security product, ask IT for the proxy’s root certificate (PEM format) and add it:

```bash
export NODE_EXTRA_CA_CERTS=/etc/ssl/certs/corp-root.pem
npm install
```

```powershell
setx NODE_EXTRA_CA_CERTS "C:\certs\corp-root.pem"
```

`NODE_EXTRA_CA_CERTS` adds the certificate to Node.js’s built-in roots when the process starts ([Node.js CLI documentation](https://nodejs.org/api/cli.html#node_extra_ca_certsfile)); `setx` takes effect in new terminals. Put the same variable in CI settings and Dockerfiles that run `npm ci`. Alternatively, if IT installed the root in the operating system, run Node.js with `NODE_USE_SYSTEM_CA=1` (Node.js 22.19 and 24.6 or later).

### A private registry uses a company CA

Artifactory, Nexus, Verdaccio or GitHub Enterprise servers often have certificates from a company CA. Test the registry with its root:

```bash
openssl s_client -connect npm.example.com:443 -servername npm.example.com -CAfile corp-root.pem </dev/null 2>/dev/null | grep 'Verify return code'
```

`Verify return code: 0 (ok)` means the root is the only thing missing. Add it with `NODE_EXTRA_CA_CERTS` as above.

### A cafile setting replaced the public roots

npm’s `cafile` and `ca` settings **replace** the default roots instead of adding to them ([npm config documentation](https://docs.npmjs.com/cli/v11/using-npm/config#cafile)). A `cafile` that holds only a company root makes the public registry fail with exactly this error. Check:

```bash
npm config get cafile
npm config get ca
```

If either is set, `NODE_EXTRA_CA_CERTS` is ignored as well, because Node.js does not add extra certificates to an explicit `ca` list ([Node.js CLI documentation](https://nodejs.org/api/cli.html#node_extra_ca_certsfile)). Remove the setting and use `NODE_EXTRA_CA_CERTS` instead:

```bash
npm config delete cafile
npm config delete ca
```

If you must keep `cafile`, make it a full bundle: the system bundle (for example `/etc/ssl/certs/ca-certificates.crt` on Debian and Ubuntu) with your company root added by `update-ca-certificates`.

### Node.js or the CA bundle is outdated

An old Node.js bundles an old set of public roots. Upgrade to a supported Node.js release.

### Related: the server leaves out its intermediate

If the code is `UNABLE_TO_VERIFY_LEAF_SIGNATURE` instead, the server sends its certificate without the intermediate. See [UNABLE\_TO\_VERIFY\_LEAF\_SIGNATURE](https://pkizerotohero.com/errors/node-unable-to-verify-leaf-signature/).

Warning

Why strict-ssl false is a trap

`npm config set strict-ssl false`, `NODE_TLS_REJECT_UNAUTHORIZED=0` and similar settings make npm accept any certificate. Packages then come from whoever answers the connection, and install scripts run with your permissions on your laptop and in your pipeline. The setting also stays in `.npmrc` long after the problem is forgotten. Add the one root you need with `NODE_EXTRA_CA_CERTS` instead.

## Check yours

*Interactive tool: Chain checker (runs in the browser at [/tools/chain/](https://pkizerotohero.com/tools/chain/))*

Paste the certificates from `openssl s_client -showcerts -connect registry.npmjs.org:443`. The checker shows the chain, names the root it ends at, and points out root names that belong to known HTTPS-inspection products.

## Learn why

- [Who do we trust? CAs, trust stores and self-signed certificates](https://pkizerotohero.com/handbook/trust-stores/): why Node.js has its own store and what TLS inspection does.
- [Certificate chains and path validation](https://pkizerotohero.com/handbook/certificate-chains/)
- Related: [SELF\_SIGNED\_CERT\_IN\_CHAIN](https://pkizerotohero.com/errors/node-self-signed-cert-in-chain/), [verify error:num=20](https://pkizerotohero.com/errors/openssl-verify-error-20/).

**Early edition.** Checked against the standards; an independent expert review is in progress. Found a mistake? [Tell us](https://pkizerotohero.com/contact/?topic=content-error&page=/errors/npm-unable-to-get-issuer-cert-locally/).

Last reviewed 20 October 2026Edition 0.9

## Learn why it happens

- [Chapter 12: Who do we trust? CAs, trust stores and self-signed certificates](https://pkizerotohero.com/handbook/trust-stores/)
- [Chapter 13: Certificate chains and path validation](https://pkizerotohero.com/handbook/certificate-chains/)

## Fix it step by step

- [How to work behind a TLS-inspecting corporate proxy, safely](https://pkizerotohero.com/guides/corporate-proxy-certificates/)
- [How to make Python, Node.js and npm trust a private CA](https://pkizerotohero.com/guides/trust-ca-python-node/)

## Everything on this topic

- [Chains and trust stores](https://pkizerotohero.com/topics/chains-and-trust/)
