Skip to content

Node.js and npm errorNode.js / npm: “Error: certificate has expired” (CERT_HAS_EXPIRED)

A request, SDK call or npm install fails with Error: certificate has expired and code CERT_HAS_EXPIRED. Node.js checked the server’s certificate chain and found a certificate past its end date, judged by your machine’s clock. With the built-in fetch, the message is TypeError: fetch failed and the code is on error.cause. Either a certificate really expired, your clock is wrong, or the client is building the chain from an outdated list of root certificates.

Short answer

Check the server certificate from the same machine (openssl s_client or curl -v). If it really expired, only the server owner can fix it by renewing. If it is valid, check the system clock, especially in containers and VMs. Then check what the client trusts: an old Node.js version, or a ca option or cafile pointing at an old certificate bundle, can still try a root certificate that has since expired. Upgrade Node.js and remove pinned bundles. Do not turn off verification.

Why the certificate looks expired, and the fix

  1. 01

    The server certificate really expired

    “'CERT_HAS_EXPIRED': Certificate has expired.” Node.js, TLS: X509 certificate error codes

    Look at the leaf certificate’s dates first. If the leaf is fine, inspect the rest of the chain (add -showcerts, or use curl -v), because an expired intermediate certificate causes the same error. If notAfter is in the past, the server needs a renewed certificate; for your own domains, check that automatic renewal (for example Let’s Encrypt via certbot or your host) is running.

    echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null | openssl x509 -noout -dates
  2. 02

    The machine’s clock is wrong

    Validity is checked against local time. A container, VM, CI runner or device with a clock far in the future, or one that lost time after sleep, sees valid certificates as expired. Sync the clock (NTP) and retry.

    date -u   # compare with the real UTC time
  3. 03

    An old CA bundle or a pinned ca option

    “Neither the well known nor extra certificates are used when the ca options property is explicitly specified for a TLS or HTTPS client or server.” Node.js, Command-line options: NODE_EXTRA_CA_CERTS

    When a root certificate expires, clients that still use it fail even though the server is fine. Old Node.js versions ship old root lists (and older OpenSSL builds do not try an alternate chain), and code that passes its own ca option, or an npm cafile, uses only that list. Upgrade Node.js, and remove or update pinned bundles.

  4. 04

    A proxy serving its own certificate

    On company networks a proxy may re-sign traffic, and its certificate can expire too. Ask IT for the current proxy root certificate and add it with NODE_EXTRA_CA_CERTS.

Checked against the vendor’s docs on : Node.js: TLS (certificate error codes); Node.js: Command-line options (NODE_EXTRA_CA_CERTS).

Rather hand it over?

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

Related: Node.js ECONNRESET (“socket hang up”) · Axios “Network Error” · JavaScript “TypeError: Failed to fetch” · “self-signed certificate in certificate chain”

Questions

More on this error

Why does the browser show the site as secure?

Browsers update their root certificates and can build a different chain to the server. An old Node.js version or a pinned bundle may only know an expired path to the same server.

Is NODE_TLS_REJECT_UNAUTHORIZED=0 acceptable as a quick fix?

No. It accepts any certificate, including an attacker’s, for every request the process makes. Fix the clock, the bundle or the server instead.

Can you fix it for me?

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.

A different error?

Describe it and get a written quote

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; Simon replies by email, usually within one business day.