<!-- https://pkizerotohero.com/errors/node-cert-has-expired/ | Markdown mirror of the HTML page | PKI Zero to Hero, by Duyutech BV -->

> Fix Node.js and npm CERT_HAS_EXPIRED: find which certificate expired, renew and reload it, check the clock, and never turn off TLS verification.

Source: https://pkizerotohero.com/errors/node-cert-has-expired/ · Last reviewed: 2026-10-20

- Node.js
- Exact text checked with the real tool

# CERT\_HAS\_EXPIRED

Also seen in: npm, yarn, axios, fetch (undici), Electron

**In one sentence:**

A certificate in the server's chain is past its end date by your machine's clock: usually the server's certificate was not renewed or reloaded; sometimes the clock is wrong.

[Check yours: Certificate decoder](https://pkizerotohero.com/tools/decoder/)

## Where you see it

In Node.js when you call an HTTPS server with `https.request`, `fetch`, axios or another client, and in npm and yarn. The code comes from OpenSSL’s verify error 10; Node.js lists it in its [TLS documentation](https://nodejs.org/api/tls.html#x509-certificate-error-codes) as “Certificate has expired”.

```text
TypeError: fetch failed
    at node:internal/deps/undici/undici:13510:13
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5) {
  [cause]: Error: certificate has expired
      at TLSSocket.onConnectSecure (node:_tls_wrap:1679:34)
      at TLSSocket.emit (node:events:507:28)
      at TLSSocket._finishInit (node:_tls_wrap:1078:8)
      at ssl.onhandshakedone (node:_tls_wrap:864:12) {
    code: 'CERT_HAS_EXPIRED'
  }
}
```

With `https.get` or axios, the same `Error: certificate has expired` with `code: 'CERT_HAS_EXPIRED'` is the error itself; with `fetch`, look in `[cause]`. npm prints:

```text
npm error code CERT_HAS_EXPIRED
npm error errno CERT_HAS_EXPIRED
npm error request to https://registry.example.com/left-pad failed, reason: certificate has expired
```

Older npm versions start these lines with `npm ERR!`. A certificate that is not valid yet gives `CERT_NOT_YET_VALID` (“certificate is not yet valid”).

## What it means

Every certificate has a [validity period](https://pkizerotohero.com/handbook/glossary/#validity-period): a `notBefore` and a `notAfter` date. Node.js checks every certificate in the [certificate chain](https://pkizerotohero.com/handbook/glossary/#certificate-chain) against the machine’s clock. For one of them, the current time is past `notAfter`, so Node.js stops the connection, even if everything else is correct. Usually the server’s own certificate expired; sometimes the client’s clock is wrong.

## Likely causes

### The server’s certificate expired

**Confirm** what the server sends right now:

```bash
openssl s_client -connect api.example.com:443 -servername api.example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -dates
```

```text
subject=CN=api.example.com
notBefore=Jan  1 00:00:00 2026 GMT
notAfter=Apr  1 00:00:00 2026 GMT
```

**Fix:** renew the certificate, install it with its full chain, and reload the server. If it is not your server, tell its owner; there is nothing safe to change on the client. For a Node.js server you run, the new files take effect only after the process restarts or calls `server.setSecureContext()` with them.

Public TLS certificates may be valid for at most 200 days since 15 March 2026, and for at most 47 days from 15 March 2029. Renew automatically and monitor what each endpoint serves: [How to check when a certificate expires, and monitor it](https://pkizerotohero.com/guides/check-certificate-expiry/).

### It was renewed, but the old certificate is still served

Common after a manual renewal or a failed reload. Compare the file with what the server sends:

```bash
openssl x509 -in /etc/ssl/api.example.com/fullchain.pem -noout -enddate
```

If the file is newer, reload or restart the service. Behind a load balancer, test each backend directly, because one node may still have the old certificate. In Kubernetes, check which Secret the ingress really uses; see [How to automate certificates in Kubernetes with cert-manager](https://pkizerotohero.com/guides/kubernetes-cert-manager/).

### An intermediate or old cross-signed certificate in the chain expired

If the server’s own certificate is valid, look at the other certificates it sends:

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

An expired intermediate left in the chain file must be replaced with the CA’s current chain ([How to build the full chain file your server needs](https://pkizerotohero.com/guides/build-fullchain/)). Old clients can also build a path through an expired cross-signed certificate even when a valid path exists, as happened when DST Root CA X3, the older root that had cross-signed Let's Encrypt, expired, so devices that did not trust ISRG Root X1 began rejecting Let's Encrypt certificates (30 September 2021). Update Node.js on such clients.

### The client’s clock is wrong

If a certificate that works everywhere else fails on one machine or container, check that machine’s time in UTC:

```bash
date -u
timedatectl status
```

Turn on time synchronisation (`sudo timedatectl set-ntp true` on systemd Linux, `w32tm /resync` on Windows). Virtual machines restored from snapshots and devices without a clock battery are typical.

Warning

Why NODE\_TLS\_REJECT\_UNAUTHORIZED=0 is a trap

`NODE_TLS_REJECT_UNAUTHORIZED=0`, `rejectUnauthorized: false` and `npm config set strict-ssl false` turn off all certificate checking, not just the expiry check: for the whole process, for every request that uses the option, or for every npm request. An expired certificate then looks the same as an attacker’s certificate, and the setting tends to stay in scripts and pipelines long after the server is fixed. Renew the certificate, or correct the clock.

## Check yours

*Interactive tool: Certificate decoder (runs in the browser at [/tools/decoder/](https://pkizerotohero.com/tools/decoder/))*

Paste the server’s certificate (the first `BEGIN CERTIFICATE` block from `openssl s_client -showcerts`). The decoder shows the validity dates and how many days are left or overdue.

## Learn why

- [Anatomy of an X.509 certificate](https://pkizerotohero.com/handbook/x509-certificates/): the validity fields.
- [Inventory, expiry and renewal](https://pkizerotohero.com/handbook/certificate-lifecycle/) and [ACME and the 47-day schedule](https://pkizerotohero.com/handbook/acme/).
- The same problem in OpenSSL: [verify error:num=10:certificate has expired](https://pkizerotohero.com/errors/openssl-certificate-has-expired/).

**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/node-cert-has-expired/).

Last reviewed 20 October 2026Edition 0.9

## Learn why it happens

- [Chapter 8: Anatomy of an X.509 certificate](https://pkizerotohero.com/handbook/x509-certificates/)
- [Chapter 19: Inventory, expiry and renewal](https://pkizerotohero.com/handbook/certificate-lifecycle/)

## Fix it step by step

- [How to check when a certificate expires, and monitor it](https://pkizerotohero.com/guides/check-certificate-expiry/)

## Everything on this topic

- [Lifecycle and automation](https://pkizerotohero.com/topics/lifecycle-and-automation/)
