Error message
certificate has expired
Also printed as
- code: 'CERT_HAS_EXPIRED'
- CERT_HAS_EXPIRED
The message text is the same in all Node.js versions; with fetch() it appears as the cause of "TypeError: fetch failed", npm prints "npm error code CERT_HAS_EXPIRED". Certificates that are not valid yet produce CERT_NOT_YET_VALID instead.
Node.js tls / https / fetch — code CERT_HAS_EXPIRED (OpenSSL X509_V_ERR_CERT_HAS_EXPIRED, 10)
What it means
A certificate in the chain Node.js built is past its notAfter date by this machine's clock. Usually it is the server's own certificate; it can also be an intermediate the server still sends, or a root from the outdated list bundled with an old Node.js release. Node.js reports the message "certificate has expired" with the code CERT_HAS_EXPIRED.
Why it happens
The server's certificate was not renewed or not reloaded
commonRenewal failed silently, or the new certificate is on disk while the server, load balancer or CDN still serves the old one.
An old Node.js with an outdated root list
occasionalNode.js compiles Mozilla's roots into the binary. A release built before a CA rolled over to a new root may know only the old, now expired root, and builds its path through it while current clients succeed.
The machine's clock is wrong
occasionalContainers inherit the host's clock; a VM restored from a snapshot or a device without a real-time clock can be far off.
How to fix it
- 1.
Read the served certificate's dates
Connect once without verification, only to read the certificate: valid_to and authorizationError show which certificate expired. Do not send data over that connection.
js // Read the dates of the served certificate (inspection only, nothing is sent) import tls from "node:tls"; const socket = tls.connect({ host: "api.example.com", port: 443, servername: "api.example.com", rejectUnauthorized: false }, () => { const cert = socket.getPeerCertificate(); console.log(cert.subject.CN, cert.valid_from, "->", cert.valid_to, "authorized:", socket.authorized, socket.authorizationError); socket.end(); }); - 2.
Renew and reload the server certificate
Renew through the ACME client or CA, reload every process that terminates TLS, then confirm the new expiry from the network side.
bash sudo certbot renew && sudo systemctl reload nginx echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null | openssl x509 -noout -enddate - 3.
Upgrade Node.js on old installations
If the server's certificate is valid for other clients, an old Node.js root list is the likely culprit; upgrading to a maintained release refreshes the bundled roots.
bash # Node.js bundles its root list: old releases carry old (or expired) roots node -v node -p "require('tls').rootCertificates.length"
Related errors
npm error code CERT_HAS_EXPIREDnpm (Node.js)curl: (60) SSL certificate problem: certificate has expiredcurl (OpenSSL backend)x509: certificate has expired or is not yet valid: current time 2026-08-20T15:4…Go crypto/x509[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has exp…Python ssl module (OpenSSL)