← Guides

"Your connection is not private" — an expired TLS certificate

NET::ERR_CERT_DATE_INVALID / certificate has expired

The moment a certificate passes its notAfter date, browsers interstitial your site (NET::ERR_CERT_DATE_INVALID), API clients throw CERT_HAS_EXPIRED, monitoring goes red, and mobile apps fail in ways users cannot bypass. Nothing about the private key or the server broke — only the validity window lapsed.

Why it happens

With 90-day Let's Encrypt certificates, expiry means renewal automation failed weeks ago and nobody noticed. The usual suspects: the ACME HTTP-01 challenge broke after a proxy/redirect change; the DNS-01 API token expired; the renewal timer/cron simply is not running; or the cert renewed on disk but the service never reloaded it (nginx/postfix keep the old file in memory). Wildcard setups also break when the DNS provider credentials rotate.

Diagnose it

Run the HTTPS/TLS check below: it shows the exact expiry date, the full served chain (a missing intermediate looks similar to users), which names the certificate covers, and the negotiated protocol. If the check shows a fresh certificate but browsers still error, the service is serving a stale file — reload it.

Fix it

1. Renew now: certbot renew --force-renewal (or your ACME client's equivalent) and reload the service.

2. Fix the underlying automation: run certbot renew --dry-run until it passes cleanly.

3. Confirm the reload hook: the renewal must end with systemctl reload nginx (or the daemon's reload).

4. Add a certificate-expiry monitor with 30/14/7/1-day alerts so a future automation failure pages you, not your users.

Diagnose your own domain in seconds:

Inspect your certificate now

Still stuck? Paste the whole bounce and we'll pinpoint the exact failure and fix.

Diagnose my bounce