How to fix npm ERR! DEPTH_ZERO_SELF_SIGNED_CERT in npm

npmINTERMEDIATEMEDIUMUpdated May 28, 2026ยท 282 views

The DEPTH_ZERO_SELF_SIGNED_CERT error occurs when npm reaches a self-signed certificate at the root of the chain (depth zero). Fix it by trusting that certificate via npm's cafile or your OS trust store.

Quick fix

Fixes npm ERR! DEPTH_ZERO_SELF_SIGNED_CERT

openssl s_client -connect your-registry:443 </dev/null 2>/dev/null \
  | openssl x509 -noout -issuer -subject
  1. Verify it is actually a self-signed certificate
  2. Export the self-signed certificate
  3. Tell npm to trust the certificate (recommended)
  4. Or add it to the system trust store
npm โ€” error
openssl s_client -connect your-registry:443 </dev/null 2>/dev/null \
| openssl x509 -noout -issuer -subject
npm ERR! DEPTH_ZERO_SELF_SIGNED_CERT

What this error means

This error indicates that the very first certificate npm encountered (at "depth zero" in the certificate chain) is self-signed. Unlike SELF_SIGNED_CERT_IN_CHAIN, where a self-signed certificate appears somewhere along an otherwise normal chain, this error means there is effectively no chain of trust at all - just a single self-signed certificate presented by the server. It commonly occurs when talking to development servers, local registries, or proxies that present certificates generated with tools like openssl or mkcert without those certificates having been added to a trusted CA store. Node.js/npm validates the certificate against the system (or configured) trust anchors, finds no matching trusted root, and aborts the TLS handshake.

Typical symptoms

  • npm install fails with DEPTH_ZERO_SELF_SIGNED_CERT
  • Error appears when accessing a local or private npm registry
  • A working development environment suddenly stops installing packages
  • Problem starts after a network or proxy change
  • Other HTTPS tools (curl, git) against the same host also fail TLS verification
  • Error is specific to one registry or host URL

Common causes

  1. Private registry serving a self-signed certificate
  2. Local npm server (Verdaccio, etc.) using its default self-signed certificate
  3. Development proxy presenting a self-signed certificate
  4. Corporate proxy intercepting TLS with a certificate not in your trust store
  5. mkcert- or openssl-generated certificate that was never added to a trust store
  6. Misconfigured reverse proxy presenting only a leaf self-signed certificate
  7. Testing/CI environment configured with an untrusted certificate

How to fix "npm ERR! DEPTH_ZERO_SELF_SIGNED_CERT"

1Verify it is actually a self-signed certificate

Inspect the certificate the registry presents:

bash
openssl s_client -connect your-registry:443 </dev/null 2>/dev/null \
  | openssl x509 -noout -issuer -subject

If the issuer equals the subject, the certificate is self-signed (depth zero), which confirms this error.

2Export the self-signed certificate

Save the certificate so you can add it to a trust store:

bash
openssl s_client -connect your-registry:443 </dev/null 2>/dev/null \
  | openssl x509 > self-signed.crt

If the registry is reachable in a browser, you can also export the certificate from the browser's certificate viewer as a PEM (.crt/.pem) file.

3Tell npm to trust the certificate (recommended)

Point npm at a CA file containing the certificate. cafile is a global npm setting - npm does not support a per-registry cafile key, so configure it once:

bash
npm config set cafile /path/to/self-signed.crt

cafile should contain the trust anchor: for a true self-signed leaf, that is the certificate itself; if the server is fronted by a private CA, use that CA's certificate. To combine your private CA with the public roots Node ships, set the environment variable instead so the default roots are kept:

bash
export NODE_EXTRA_CA_CERTS=/path/to/self-signed.crt

This is the safest fix because TLS verification stays enabled - you are only adding a new trust anchor, not disabling checks.

4Or add it to the system trust store

Trusting the certificate at the OS level fixes npm and every other TLS client (git, curl, etc.) at once:

bash
# Ubuntu/Debian
sudo cp self-signed.crt /usr/local/share/ca-certificates/your-registry.crt
sudo update-ca-certificates

# RHEL/Fedora
sudo cp self-signed.crt /etc/pki/ca-trust/source/anchors/your-registry.crt
sudo update-ca-trust

# macOS
sudo security add-trusted-cert -d -r trustRoot \
  -k /Library/Keychains/System.keychain self-signed.crt

# Windows (run PowerShell/cmd as admin)
certutil -addstore -f "ROOT" self-signed.crt

On Linux, set NODE_EXTRA_CA_CERTS (see step 3) or npm config set cafile as well, because Node does not automatically read the system store.

5For local development, use mkcert

mkcert installs a local CA into your system (and browser) trust stores, so certificates it issues are trusted automatically - avoiding self-signed errors entirely:

bash
# Install mkcert (examples)
brew install mkcert       # macOS
# choco install mkcert    # Windows
# apt install mkcert      # Debian/Ubuntu (or download the release binary)

# Install the local CA into the trust stores
mkcert -install

# Generate a certificate for your local registry host
mkcert localhost 127.0.0.1 ::1

Serve your local registry with the generated *.pem files and npm will trust them with no further configuration.

6Last resort: disable strict SSL (development only)

Prefer the trust-based fixes above. Only if you cannot obtain or install the certificate (for example, a throwaway local test) should you temporarily turn off verification. This disables TLS certificate checks entirely and exposes you to man-in-the-middle attacks, so never do this for production, shared, or CI machines, and re-enable it immediately afterward.

bash
# Per-command (preferred - scoped, not persisted)
npm install --strict-ssl=false

# Or globally (remember to undo it)
npm config set strict-ssl false
# ...then re-enable:
npm config set strict-ssl true

Advanced notes

For production private registries, use certificates issued by a real CA (Let's Encrypt is free and automatable) rather than self-signed certificates, so no client-side trust configuration is needed. In Kubernetes, manage certificates with cert-manager. For local development, mkcert creates locally-trusted certificates that work across tools without per-client setup.

Note the distinction between npm's trust settings: cafile/ca and strict-ssl are global npm config keys, not per-registry keys - only authentication settings (such as //registry:port/:_authToken or :username) are scoped per registry. To make Node itself trust a private CA without replacing its built-in roots, prefer the NODE_EXTRA_CA_CERTS environment variable, which is additive. When distributing to a team, ship the CA via configuration management or document the OS trust-store install steps so every machine trusts it consistently.

Frequently asked questions

What does "npm ERR! DEPTH_ZERO_SELF_SIGNED_CERT" mean?
This error indicates that the very first certificate npm encountered (at "depth zero" in the certificate chain) is self-signed. Unlike SELF_SIGNED_CERT_IN_CHAIN, where a self-signed certificate appears somewhere along an otherwise normal chain, this error means there is effectively no chain of trust at all - just a single self-signed certificate presented by the server. It commonly occurs when talking to development servers, local registries, or proxies that present certificates generated with tools like openssl or mkcert without those certificates having been added to a trusted CA store.
How do I fix "npm ERR! DEPTH_ZERO_SELF_SIGNED_CERT"?
The DEPTH_ZERO_SELF_SIGNED_CERT error occurs when npm reaches a self-signed certificate at the root of the chain (depth zero). Fix it by trusting that certificate via npm's cafile or your OS trust store.
What causes "npm ERR! DEPTH_ZERO_SELF_SIGNED_CERT"?
Private registry serving a self-signed certificate Local npm server (Verdaccio, etc.) using its default self-signed certificate Development proxy presenting a self-signed certificate
Is the "npm ERR! DEPTH_ZERO_SELF_SIGNED_CERT" error serious?
It is a medium-severity error โ€” more of a blocker than a risk. The steps above resolve it.

Official resources & further reading