SSL Certificate Expired Without Warning
Renewing is usually the easy part. The step people miss is reloading the server, and a renewed certificate on disk is not a certificate being served.
Confirm what is actually being served before you renew anything, because a certificate that renewed correctly and was never loaded looks identical to one that never renewed.
Compare that against the file on disk. If the file is current and the served certificate is not, you do not have a renewal problem. You have a reload problem, and the fix is one command.
If it genuinely has not renewed
Force a renewal now and read the output rather than letting it run quietly.
Verify from a machine other than the server. Checking from the server itself can hit a local cache or a different vhost and tell you something reassuring and wrong.
The error strings, so you know what you are looking at
| Where you saw it | Message |
|---|---|
| Chrome / Edge | NET::ERR_CERT_DATE_INVALID |
| Firefox | SEC_ERROR_EXPIRED_CERTIFICATE |
| curl | SSL certificate problem: certificate has expired |
| Go | x509: certificate has expired or is not yet valid |
| Python requests | CERTIFICATE_VERIFY_FAILED: certificate has expired |
| Java | PKIX path validation failed ... NotAfter |
| Node | CERT_HAS_EXPIRED |
Why no warning reached you
Work down this list. In practice it is one of the first three.
The renewal timer was disabled. A server rebuild, a package upgrade or a container image change can drop the systemd timer or the cron entry without anyone noticing, and certbot only warns you when it runs.
The renewal succeeded and the service was never reloaded. Certbot's deploy hook is what does this, and a hand-written configuration frequently lacks one. The certificate on disk is fine and the running process is still holding the old one in memory.
The renewal was failing for weeks and the notification emails went nowhere. Let's Encrypt emails the address registered with the ACME account, which is often a personal address from whoever set it up. ACME challenge failures after a DNS change or a redirect rule are the usual underlying cause.
The certificate was renewed on one node and not another. Load balancers, CDN edges and a second application server all serve certificates independently, and checking one proves nothing about the others.
This is going to happen more often
Maximum TLS certificate lifetime dropped from 398 days to 200 on 15 March 2026 under CA/Browser Forum ballot SC-081v3, falling to 100 days in March 2027 and 47 in March 2029.
Any process that worked because renewal only came round once a year is now exercised twice as often, and will be exercised roughly eight times a year by 2029. A renewal path that fails one time in ten was survivable annually and is not survivable at that cadence.
Stopping the repeat
Monitor the certificate as served over the network, not the file on disk, and check every hostname including the ones nobody thinks of as production. The endpoint that takes you down is usually an internal API or a legacy subdomain that ACME was never pointed at.
That external check is what SensaCat and similar tools do on a schedule. The wider context is in SSL certificate monitoring.