Skip to content
RU
← All articles

Expired SSL Certificate: How to Fix NET::ERR_CERT_DATE_INVALID

In short. Renewing the certificate is the obvious fix and it is not usually where the time goes. In practice the certificate has often already been renewed and the server is still serving the old one, or auto-renewal stopped working months ago for a reason nobody noticed. Establish which of those you have before buying anything.

First: is the certificate expired, or is your clock wrong?

Both produce the same browser error, and they have opposite owners. This takes ten seconds and eliminates half the possibilities.

# What window does the server's certificate claim?
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -dates
# notBefore=... / notAfter=...

# What does your machine think the time is?
date -u

If your clock is outside the window and the certificate looks valid to everyone else, the fault is local. If your clock is right and notAfter is in the past, the certificate genuinely expired and only the site can fix it.

The SSL checker settles this from outside your network, which is faster than arguing about it — it has no relationship to your machine's clock or your trust store.

An expired certificate does not fail gradually. It works perfectly until a specific second and then fails for every visitor at once. There is no partial state and no warning phase, which is why it is one of the few outages that arrive fully formed.

A validity window with a hard boundary, showing traffic passing on one side and stopping entirely on the other
Validity has a hard edge. The certificate works until a specific second and then fails for everyone simultaneously.

The most common real cause: it was renewed and never reloaded

Automated renewal writes new files to disk. It does not, by itself, make a running web server use them — the server read the certificate at startup and holds it in memory. Without a reload the new file sits on disk while the old one keeps being served.

This is the single most frequent version of the problem, and it is invisible if you check the filesystem instead of the connection. The file says renewed; the wire says expired.

# What the file on disk says
openssl x509 -enddate -noout -in /etc/letsencrypt/live/example.com/fullchain.pem

# What the server actually serves — these can disagree
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -enddate -noout

# Different dates? Reload, do not restart, to avoid dropping connections
nginx -t && systemctl reload nginx
apachectl configtest && systemctl reload apache2

Make the reload part of renewal rather than a thing you remember. A deploy hook runs it automatically every time, including the renewal that happens while you are asleep.

# certbot: run this after every successful renewal
certbot renew --deploy-hook "systemctl reload nginx"

# verify the whole path without waiting for the real expiry
certbot renew --dry-run

Why auto-renewal silently stopped

Renewal is a background process, so when it breaks it breaks quietly and you discover it roughly ninety days later. Five causes account for most of it:

CauseHow it presentsHow to confirm
Port 80 closed or redirectedHTTP validation cannot completeFetch the challenge path over plain HTTP
Nameservers changedDNS validation fails for wildcardsCheck the NS set against the registrar
Renewal timer disabledNothing has run in monthsInspect the timer or cron entry
Hostname removed from the zoneOne name in the set no longer resolvesResolve every name on the certificate
Rate limit reachedRepeated failed attempts hit a ceilingRead the renewal log
# Is the renewal mechanism alive at all?
systemctl list-timers | grep -i certbot
crontab -l | grep -i certbot
ls -la /etc/cron.d/ | grep -i certbot

# When did it last succeed, and what did it say?
journalctl -u certbot --since '90 days ago' --no-pager | tail -30

# HTTP validation needs port 80 reachable and not redirected away
curl -sS -o /dev/null -w 'port 80: %{http_code}\n' \
  http://example.com/.well-known/acme-challenge/probe

A redirect from HTTP to HTTPS is good practice and it must exclude the challenge path. Redirecting /.well-known/acme-challenge/ to HTTPS breaks validation on a site whose certificate has just expired — the renewal needs the connection that the expired certificate is refusing.

That last point produces the deadlock people find most confusing: the certificate expired, so HTTPS fails, so the redirect sends validation to a broken HTTPS endpoint, so renewal cannot fix the certificate. Serving the challenge path over plain HTTP breaks the loop.

The endpoint nobody renewed

Certificates are per-service, not per-domain. Renewing the one on 443 does nothing for the others, and the others are the ones that fail without a visible browser error:

  • Mail. An expired certificate on the submission or IMAP port stops clients from sending and receiving, and mail clients report it in ways users describe as "email is broken".
  • APIs on other ports. Nothing browses them, so nobody sees the interstitial — integrations simply start failing.
  • Admin panels and internal tools, often on a different host with a different renewal setup.
  • Load balancer or CDN termination. If TLS terminates at the edge, the certificate that matters may not be on your server at all.
# Check every TLS port you actually run, not just 443
for hp in example.com:443 example.com:8443 mail.example.com:465 mail.example.com:993; do
  printf '%-28s ' "$hp"
  echo | openssl s_client -connect "$hp" -servername "${hp%%:*}" 2>/dev/null \
    | openssl x509 -enddate -noout 2>/dev/null || echo 'no certificate returned'
done
One domain with several service endpoints, each holding its own certificate, one of which has lapsed
Certificates belong to services, not to domains. Renewing the public site leaves mail and API endpoints on their own schedule.

Renewing it now

Let's Encrypt and other ACME issuers

# Force renewal when the automatic path has failed
certbot renew --force-renewal --deploy-hook "systemctl reload nginx"

# If HTTP validation is blocked, validate over DNS instead
certbot certonly --manual --preferred-challenges dns \
  -d example.com -d www.example.com

# Confirm what the server now serves — not what the file says
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -dates -subject -ext subjectAltName

Commercial certificates

Reissue through the authority, then install the leaf and its intermediates. Installing only the leaf converts an expiry problem into an untrusted-issuer problem — browsers often hide that by fetching the missing intermediate themselves, so the site appears fixed while every API client and server-to-server call keeps failing. The chain guide covers reassembly, and the strict-client guide covers why browsers hide it.

When you need service back before the certificate arrives

There is no safe way to make browsers accept an expired certificate, and telling users to click through trains them to ignore the warning that protects them. The realistic options are an ACME certificate issued in minutes as a stopgap, or terminating TLS temporarily at a CDN that holds its own certificate. Both restore trust properly; neither asks the visitor to lower their guard.

After renewal: what to actually verify

  1. The dates on the wire, not on disk. This catches the missing reload.
  2. The certificate count. Fewer than two usually means the chain was not installed.
  3. Every hostname on the certificate, including www and any name a redirect targets.
  4. Every port that terminates TLS, not just 443.
  5. From outside your network, because an intermediate cached locally can mask an incomplete chain.
echo | openssl s_client -connect example.com:443 -servername example.com -showcerts 2>/dev/null \
  | grep -c 'BEGIN CERTIFICATE'    # expect 2 or more
echo | openssl s_client -connect example.com:443 -servername example.com \
  -verify_return_error 2>&1 | grep 'Verify return code'   # expect 0 (ok)

Making it not happen again

Expiry is the most preventable outage there is: the date is known in advance, precisely, from the moment the certificate is issued. What fails is not knowledge but noticing.

ApproachCatches a broken renewal?Why
Calendar reminderNoReminds a person who will assume automation handled it
Issuer expiry emailsPartlyArrive late, to an address that may no longer be read
Checking the file on diskNoThe file can be current while the server serves the old one
Renewal exit codesPartlyCatches failure, not a timer that stopped running
External check of the served certificateYesMeasures what visitors receive, from where they are

Only the last row survives every failure mode above, because it tests the connection rather than the intention. SSL monitoring checks the served certificate on a schedule and alerts on remaining days, so a renewal that quietly stopped working surfaces weeks before it becomes an outage rather than on the morning it does.

A countdown of remaining validity with an early alert threshold well before the expiry boundary
The date is known from the day of issue. What fails is noticing, which is why the alert has to come from outside.

How to check right now

Run the SSL checker for the dates, the chain and the covered names in one pass from outside your network. Use the port checker to confirm port 80 is reachable if renewal validation is failing, and the redirect tracer to check that your HTTP-to-HTTPS redirect does not swallow the ACME challenge path — the deadlock described above.

If this has happened more than once, the fix is not a better reminder. Continuous SSL monitoring watches remaining validity on every endpoint you register and reports the certificate as served, which is the only measurement that catches a renewal that runs successfully and changes nothing.

A file on disk showing a fresh date beside a server connection still presenting an old certificate
Disk and wire can disagree. Checking the file is what makes a missing reload invisible.

Frequently asked questions

Can I keep using a site with an expired certificate?

Browsers will let a user click through, and doing so removes the protection for that session. For anything handling logins, payments or personal data, treat the site as down until the certificate is valid — that is effectively how visitors will treat it anyway.

I renewed it and the error is still there.

Almost always a missing reload: the new file exists and the running server still holds the old certificate in memory. Compare the date on disk with the date the server actually serves. If they differ, reload.

Why did auto-renewal stop without telling anyone?

Because the failure is a background process exiting non-zero, and nothing was watching. The usual causes are a blocked validation path, changed nameservers, or a timer that stopped running after a system change. Renewal logs will say which.

My HTTP-to-HTTPS redirect breaks renewal. What now?

Exclude the ACME challenge path from the redirect so it is served over plain HTTP. Otherwise validation is sent to an HTTPS endpoint that is failing because of the very certificate you are trying to renew.

How long is a Let's Encrypt certificate valid?

Ninety days, and renewal is expected to run automatically well before that. The short lifetime is deliberate: it forces automation, and automation that runs monthly fails visibly long before a yearly one would.

What if the certificate is revoked rather than expired?

Different error and a different severity. Revocation usually means the private key was compromised, so reissue with a new key pair and find out how the old one leaked. Reusing the key reissues the problem.

Does an expired certificate affect email?

Yes, if mail services present it. Clients may refuse to send or receive, and the failure is reported by the mail client rather than by a browser — which is why it is often diagnosed as "email is broken" rather than as a certificate problem.

Checklist

  • Compare your clock against the certificate dates before assuming expiry.
  • Check the date on the wire, not the date on disk.
  • Reload the server after renewal — make it a deploy hook, not a habit.
  • Verify the renewal timer has actually been running.
  • Exclude the ACME challenge path from the HTTPS redirect.
  • Check every TLS port, including mail and APIs.
  • Confirm at least two certificates are served after installing a commercial one.
  • Validate every hostname the certificate is supposed to cover.
  • Never ask users to click through the warning.
  • Monitor the served certificate externally — no other method catches a silent renewal failure.

Check your website right now

Check your site's SSL →
More articles: SSL/TLS
SSL/TLS
SSL Certificate Chain: How to Verify and Fix an Incomplete One
15.04.2026 · 1 154 views
SSL/TLS
Fix ERR_CERT_AUTHORITY_INVALID: Causes and Solutions
13.07.2026 · 1 012 views
SSL/TLS
SSL Handshake Failed: Root Causes and Step-by-Step Diagnosis
15.04.2026 · 935 views
SSL/TLS
Weak Cipher Suites: Find and Disable Insecure TLS Ciphers
15.04.2026 · 841 views