If you are seeing x509: certificate has expired or is not yet valid, a TLS certificate in the chain was rejected during the handshake because the current time sits outside its validity window. The client compared “now” against the certificate notBefore and notAfter fields and refused the connection. This is a hard stop: auth is blocked until the certificate, the chain, or the clock is corrected. Resist the urge to regenerate immediately, because half the time the certificate is fine and the clock is wrong.
What this error means
Every X.509 certificate carries two timestamps: notBefore and notAfter. During the TLS handshake the client checks that its own idea of the current time falls between those two values. If the certificate has aged past notAfter, or the client clock is set earlier than notBefore, the certificate is treated as invalid and the connection is dropped. The same error covers both a genuinely expired certificate and a client whose clock is simply wrong.
Common causes
- The leaf certificate genuinely expired (it passed notAfter and was never renewed).
- An intermediate or root in the chain expired, even though the leaf is current. This is the pattern behind the well known Let’s Encrypt DST Root CA X3 expiry, where old CA bundles broke connections.
- The client clock is wrong. Skewed or reset time makes a valid certificate look expired or not yet valid, which is common in containers, virtual machines, and IoT devices with no reliable NTP.
- The certificate was renewed on disk but the service still serves the old one from memory because it was never reloaded.
- The wrong certificate is being served, or the endpoint omits required intermediate certificates so the chain cannot be built.
How to fix it
Stabilize
- First rule out the clock, because it is fast to check and fixes many incidents instantly.
date
timedatectl status
- If the time is wrong, correct it with NTP before touching any certificate.
sudo timedatectl set-ntp true
sudo systemctl restart chronyd # or: sudo systemctl restart systemd-timesyncd
chronyc tracking
Diagnose
- Inspect the certificate the endpoint actually presents, including its dates and chain.
openssl s_client -connect example.com:443 -servername example.com < /dev/null 2>/dev/null \
| openssl x509 -noout -subject -dates
- Check a local certificate file directly.
openssl x509 -noout -subject -issuer -dates -in /etc/ssl/certs/example.pem
- Verify the full chain resolves against your CA bundle. A verify error here points at a missing intermediate or an expired root.
openssl s_client -connect example.com:443 -servername example.com -showcerts < /dev/null
Read notBefore and notAfter against the current date. If notAfter is in the past, the certificate is expired. If notBefore is in the future relative to a correct clock, it is not yet valid.
Fix
- If the certificate is expired, renew it. With certbot:
sudo certbot renew --force-renewal
- Reload the service so it reads the new certificate from disk.
sudo nginx -t && sudo nginx -s reload
# or, for a systemd managed service:
sudo systemctl reload nginx
- In Kubernetes with cert-manager, inspect and force the renewal.
kubectl get certificate -A
kubectl describe certificate my-cert -n my-namespace
cmctl renew my-cert -n my-namespace
- If an expired root is the cause, update the trusted CA bundle.
sudo update-ca-certificates # Debian and Ubuntu
sudo update-ca-trust extract # RHEL and Fedora
How to prevent it
- Automate renewal so certificates never reach notAfter by hand. Use the certbot systemd timer or cert-manager, and confirm the timer is active with
systemctl list-timers. - Add expiry monitoring that alerts well ahead of notAfter, for example 30 and 7 days out, on leaf and intermediate certificates.
- Run NTP everywhere, including containers, virtual machines, and edge devices, so clock skew cannot masquerade as an expired certificate.
- Attach a reload hook to renewal (certbot
--deploy-hook) so the service always picks up the new certificate automatically. - Serve the full chain, including intermediates, and keep CA bundles current across every host.
When to call a senior engineer
Call for help when the certificate and clock both check out but the handshake still fails, when an expired intermediate or root is breaking many services at once, or when a renewal loop or load balancer keeps serving a stale certificate you cannot trace. If the outage is customer facing and every minute counts, Erzon can pair with you live, confirm the real cause, and restore the handshake while your team keeps working the incident.
Related errors we fix
TokenExpiredError: jwt expired Fix this error → Authentication JsonWebTokenError: invalid signature Fix this error → Authentication invalid_grant: The provided authorization grant is invalid, expired, or revoked Fix this error → Authentication SSL certificate problem: unable to get local issuer certificate Fix this error → Want a senior engineer to just fix it?
Paste this exact error into the form. A senior engineer replies within one business hour with what is likely wrong and a flat quote. Triage is free.
Book a fix