Guide
Node.js UNABLE_TO_VERIFY_LEAF_SIGNATURE / expired
Node.js throws certificate has expired when OpenSSL rejects HTTPS server notAfter. Reproduce with node -e or fetch, confirm the live cert, renew the listener, and remove NODE_TLS_REJECT_UNAUTHORIZED shortcuts.
Updated May 2, 2026 810 words
node.js certificate has expired means the runtime’s OpenSSL trust check failed—usually notAfter on the HTTPS host your code calls, not a bug in the https module or fetch.
Microservices log ERR_TLS_CERT_ALTNAME_INVALID, UNABLE_TO_VERIFY_LEAF_SIGNATURE, or certificate has expired during webhook delivery. Serverless functions fail cold starts that call third-party APIs.
Teams sometimes export NODE_TLS_REJECT_UNAUTHORIZED=0 in production env vars. That hides expiry while exposing traffic to interception. Fix the remote listener, then keep verification enabled.
First response
Capture the full stack trace, Node major version, exact URL, and whether a corporate proxy sits in path. Save minimal reproduction script output and openssl dates for the same hostname and port. Mention npm config cafile or custom agent settings if used.
Note if only alpine-based containers fail—older musl images ship sparse CA bundles, but expired server certs fail on every platform when dates are past notAfter.
Link curl SSL certificate expired when libcurl and Node share the same broken partner host, and Python requests SSL expired for polyglot pipelines hitting the same URL.
What this error means
Node delegates TLS to OpenSSL or BoringSSL in some builds. After the server sends its chain, Node verifies signatures, builds a trusted path, checks hostname against SANs, and enforces validity windows.
When notAfter passed, verification throws before your application receives HTTP status codes. UNABLE_TO_VERIFY_LEAF_SIGNATURE often appears alongside expiry when the chain cannot be built—still read openssl -showcerts to see whether an expired intermediate is the culprit.
Redirects matter: axios following 302 to another host may fail on a different certificate. Log the final URL hostname in errors.
Common causes
Partner API certificate expired. Outbound integrations break while your own website cert remains fresh.
Stale cert on internal service mesh ingress. Pods call https URLs through a gateway presenting old PEM files.
Puppeteer calling expired staging. CI uses production trust settings against expired preview environments.
Custom https.Agent pinning old intermediates. Code bundles a CA file that expired even though the public web trusts a cross-sign.
Load balancer default cert. Missing servername option causes connection to wrong vhost with expired default.
Long-lived serverless with cached DNS. Rare, but always confirm openssl on the hostname at failure time.
Confirm from the outside
Minimal Node repro
node -e "require('https').get('https://HOST/', (r) => console.log(r.statusCode)).on('error', (e) => { console.error(e.code, e.message); process.exit(1); })"
Fetch API
node -e "fetch('https://HOST/').then(r=>console.log(r.status)).catch(e=>console.error(e.cause||e))"
OpenSSL same host
echo | openssl s_client -connect HOST:443 -servername HOST 2>/dev/null | openssl x509 -noout -dates -subject
How to read the output
Node’s code may be CERT_HAS_EXPIRED or DEPTH_ZERO_SELF_SIGNED_CERT depending on chain shape. openssl notAfter is authoritative for whether renewal is required. If dates are valid but Node still fails, inspect custom CA files and proxy MITM roots.
Fix checklist
- Re-run the one-line Node repro without NODE_TLS_REJECT_UNAUTHORIZED.
- Identify terminating hostname from verbose logs or redirect chain.
- Renew certificate on that listener with full chain.
- Reload nginx, ingress, API gateway, or CDN custom cert.
- Redeploy containers only if they serve TLS—not when they are clients only.
- Remove rejectUnauthorized: false from agents and SDK configs.
- Re-run integration tests and webhooks.
- Add live TLS monitor on outbound critical hostnames.
Archive openssl serial before and after renewal in the ticket. Remove temporary env vars from Kubernetes Secrets and CI variable groups when verification succeeds again.
For node.js certificate has expired rollouts, redeploy only after openssl on the dependency URL shows a new serial. If you use PM2 or systemd for Node workers, restart after remote renewals even when the process only acts as a client—cached connection pools may mask success until the next deploy. Keep a pinned openssl command in the service README so the next on-call reproduces the incident in one step.
During triage, reject myths that upgrading LTS Node alone fixes expiry, or that Docker base image swaps replace server renewal. Both can change error strings but cannot accept an expired partner leaf. If only serverless invocations fail, check whether the function reaches the internet through a NAT gateway with SSL inspection using an expired re-sign cert—openssl from a comparable subnet clarifies that split.
When incidents cluster around node.js certificate has expired, archive the failing URL in your service catalog with owner and renewal contact. Controllers that call webhooks should log TLS errors with hostname attached so openssl targets the right listener on the first try. After renewal, run the same Node one-liner from CI that production uses—local laptop success alone is not enough when runners live in a different VPC.
When to use automation
Node services call dozens of partner URLs—monitor each integration endpoint’s live TLS, not only your marketing domain. Use /check for public APIs you depend on; schedule alerts at 30, 14, 7, and 1 days so webhook owners renew before queues back up.
Pair with RDAP on callback domains when legal holds delay OV revalidation.
Frequently asked questions
Why UNABLE_TO_VERIFY_LEAF_SIGNATURE not CERT_HAS_EXPIRED?
An incomplete chain prevents building a path to a trusted root; sometimes an expired intermediate produces the same string. Use openssl s_client -showcerts.
Alpine-only failures?
Confirm musl image has current Mozilla CA bundle, but first rule out expired partner cert with openssl from the same container.
mTLS client cert expired?
Server errors differ (alert bad certificate). This guide targets server leaf expiry on outbound HTTPS. Inspect client cert dates separately for mutual TLS.
Can I pass ca with the old cert?
Pinning the expired cert worsens the outage. Install updated CA chain from the issuer and remove temporary bypass env vars.
See what the server presents right now
Free live certificate check — no signup.