NET::ERR_CERT_DATE_INVALID: causes and fixes
Chrome shows NET::ERR_CERT_DATE_INVALID when the certificate expired or the visitor's clock is wrong. How to tell which, renew it and get warned in time.
NET::ERR_CERT_DATE_INVALID is Chrome's and Edge's error for a certificate that isn't valid on today's date: it expired, or it isn't valid yet. Firefox calls the same thing SEC_ERROR_EXPIRED_CERTIFICATE, Safari says the certificate "has expired". Either the site's certificate really is outside its dates, or the visitor's computer has the wrong date.
Is it the site or the visitor?
Check the certificate from another machine. If it's expired there too, the problem is the server:
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
Replace example.com with the host. A healthy certificate:
subject=CN=lampwick.dev
issuer=C=US, O=Let's Encrypt, CN=YE1
notBefore=Nov 7 13:17:13 2026 GMT
notAfter=Feb 5 13:17:12 2027 GMT
An expired one, tested against expired.badssl.com:
notBefore=Apr 9 00:00:00 2015 GMT
notAfter=Apr 12 23:59:59 2015 GMT
curl https://example.com/ says curl: (60) SSL certificate problem: certificate has expired for the same case. If notAfter is in the future and only one visitor sees the error, it's on their side.
Fixes on the visitor's side
- The device clock is wrong. The most common visitor-side cause: a PC with a dead CMOS battery, a phone set to manual time, a virtual machine restored from a snapshot. Turn on automatic date and time and reload.
- Antivirus or a company proxy intercepts HTTPS. It re-signs every site with its own certificate; when its own clock or certificate is off, every site fails. Test on another network.
- A very old device. It doesn't know newer root certificates and may report an expired chain. Updating the OS or browser is the only real fix.
If you run the site, none of these are yours to fix, but check the server first: a visitor reporting this is often the first sign that renewal failed.
Fixes on the server: the certificate expired
Certificates expire on purpose, and they're getting shorter. The CA/Browser Forum voted in April 2025 (ballot SC-081v3) to cut the maximum lifetime of public TLS certificates from 398 days to 47 days between March 2026 and March 2029: 200 days from 15 March 2026, 100 days from 15 March 2027, 47 days from 15 March 2029 (DNSimple's summary). Let's Encrypt issues 90-day certificates today and moves its default to 64 days on 10 February 2027 and 45 days on 16 February 2028 (Let's Encrypt). All checked on 10 Nov 2026. Renewing by hand once a year no longer works: renewal has to be automatic, and you need to know when the automation breaks.
Renew now with certbot, then find out why it didn't renew on its own:
sudo certbot certificates
sudo certbot renew --dry-run
sudo certbot renew
certbot certificates lists each certificate with its expiry date. --dry-run tests renewal against Let's Encrypt's staging server without changing anything, and shows the error if there is one.
Renewal isn't scheduled
certbot installs a systemd timer or a cron job, and a server rebuilt from a script or a container without it never renews. Check:
systemctl list-timers | grep certbot
No line means no schedule. With the snap package, sudo systemctl enable --now snap.certbot.renew.timer; otherwise add a cron entry that runs certbot renew twice a day.
The challenge fails
Let's Encrypt has to reach your server to prove you control the domain. --dry-run shows which part fails:
- Port 80 is closed. HTTP-01 validation always starts on port 80, even when the site only serves HTTPS. Open it in the firewall and security group.
- A redirect or a new deploy broke
/.well-known/acme-challenge/. A changed web root, a catch-all route in your app, or a CDN that doesn't pass the path through. With certbot's--webrootmode, the web root must still be the directory the server serves. - DNS moved. The domain now points at a new server or a CDN, so the challenge never reaches the server that runs certbot. Renew where the traffic goes, or use DNS-01 validation.
The certificate renewed, but the server still serves the old one
Nginx, Apache and HAProxy read the certificate at start and keep it in memory. If nothing reloads them after renewal, the new file sits on disk while visitors get the expired one. Add a deploy hook, which certbot runs after every successful renewal:
printf '#!/bin/sh\nsystemctl reload nginx\n' | sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-nginx
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-nginx
Then check what the server actually serves with the openssl s_client command above, not the file on disk.
Another server or the CDN has its own certificate
Behind a load balancer or CDN, the visitor sees the certificate of whatever terminates TLS. One node with an old certificate gives the error to some visitors only. An origin certificate behind Cloudflare that expired gives Cloudflare error 526 instead. Check each node by its own IP:
echo | openssl s_client -connect 203.0.113.10:443 -servername example.com 2>/dev/null | openssl x509 -noout -enddate
203.0.113.10 is the node's IP; -servername still sends the real host name.
Hosted platforms
On Vercel, Netlify, Lovable, Laravel Cloud, Forge and similar, the platform renews for you, as long as the domain's DNS still points at it. Renewal usually breaks when DNS was changed or a CAA record doesn't allow the platform's certificate authority. Check the domain's status in the platform's dashboard.
Get warned before it expires
Since 4 June 2025 Let's Encrypt no longer emails you before a certificate expires (Let's Encrypt, checked 10 Nov 2026). If renewal breaks, the first warning is often a visitor's screenshot of this error.
Every Lampwick uptime monitor also checks its URL's certificate from outside, every 6 to 12 hours. It alerts the team 14, 7, 3 and 1 days before expiry, and once when the certificate becomes invalid: expired, for the wrong host or from an unknown issuer. Because it reads the certificate the server actually serves, it also catches the "renewed but not reloaded" case. The details are in SSL, domain and DNS checks; SSL certificate monitoring has the overview.
For the other reasons a site goes offline, such as an expired domain or a DNS change, see how to know when your app is down.