Skip to content

Fix ERR_CERT_DATE_INVALID

Short answer

ERR_CERT_DATE_INVALID means the browser compared the certificate's validity window against its own clock and found no overlap. Three things cause it: the certificate really has expired, the device clock is wrong, or the server is presenting a different certificate than you expect. Check the server's dates from a second machine first.

Check it yourself
SSL Certificate Checker
Expiry, chain completeness, and certificate details

This error is a comparison, not a verdict about the certificate. Chrome takes the notBefore and notAfter fields from the certificate the server presented, compares them to the system clock, and refuses if today falls outside that window. Two variables feed that comparison — the certificate and the clock — and either can be the broken one. Firefox reports the same condition as SEC_ERROR_EXPIRED_CERTIFICATE, Safari as "this certificate has expired", and curl as certificate has expired (exit code 60).

How do I tell the three causes apart in under a minute?

Do not start with the browser. Start with a command-line client on a machine you trust, because it tells you what the server actually sent and what a correct clock thinks of it.

echo | openssl s_client -connect example.com:443 -servername example.com 2>&1 \
  | grep -E "verify error|Verify return code|notAfter"

# Genuinely expired certificate:
# verify error:num=10:certificate has expired
# notAfter=Apr 12 23:59:59 2015 GMT
#     Verify return code: 10 (certificate has expired)

# Healthy server (so the problem is the client):
#     Verify return code: 0 (ok)
The one command that separates all three causes

Read the result like this:

  1. `notAfter` is in the past and verify code is 10 — the certificate really has expired. Renew it. Skip to the renewal section below.
  2. `notAfter` is comfortably in the future and verify code is 0 — the server is fine. The problem is on the complaining device: its clock, or the fact that it is reaching a different server than you just tested.
  3. `notAfter` is in the future but the subject is not the hostname you expected — you are being served the wrong certificate. That is an SNI or vhost problem, covered below.
SSL Certificate Checker
Expiry, chain completeness, and certificate details

Cause 1: the certificate genuinely expired

The boring case, and still the most common. Public TLS certificates are short-lived and getting shorter; automated renewal is the only sustainable answer. When automation is in place and the certificate expired anyway, the failure is almost always one of a small set:

  • The renewal ran but the service was never reloaded. nginx and Apache hold certificates in memory. A new file on disk changes nothing until you reload. Check the on-disk date against the on-the-wire date — if they differ, this is your answer.
  • The ACME HTTP-01 challenge broke. A redirect rule, an HSTS-forcing config, or a WAF that now blocks /.well-known/acme-challenge/ will fail renewal silently for weeks. Trace what a request to that path actually does with the Redirect Checker.
  • A CAA record blocks your CA. If someone tightened the zone, your CA is refused at issuance time. Check with the CAA Record Lookup.
  • DNS-01 validation broke after a nameserver change. The renewal client is writing TXT records into a zone that is no longer authoritative. Confirm with the NS Record Lookup and TXT Record Lookup.
  • The renewal timer is not running. systemd timer disabled, cron removed during a migration, or the container that held it was rebuilt.

Compare what is on disk with what is on the wire — the discrepancy is diagnostic:

# What the renewal client wrote:
openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -noout -dates

# What the server is actually presenting:
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -dates

# Different? Reload the service:
#   nginx -t && systemctl reload nginx
#   apachectl configtest && systemctl reload apache2
On-disk vs served certificate

Cause 2: the client clock is wrong

If the server checks out clean from your machine but one user still sees the error, their device thinks it is a different date. TLS validation has no way to know that, so it blames the certificate. The tell is that every HTTPS site fails, not just yours — ask the user to try two or three unrelated sites.

Classic sources of a wrong clock: a dead CMOS battery resetting a desktop to the BIOS epoch, a phone or laptop restored from a long-powered-off state, a virtual machine resumed from a snapshot, a container built without NTP, or a device whose timezone is right but whose date is a year out. A clock that is *ahead* produces the same error against a perfectly valid certificate — the browser thinks notAfter has already passed.

Quick check for the user: open the clock and confirm both the date and the year. On Windows, Settings → Time & language → set time automatically off/on forces a resync. On macOS, System Settings → General → Date & Time. On Linux, timedatectl shows whether NTP is synchronised.

A related trap: a certificate that has not started yet. If notBefore is in the future — because it was just issued and the client's clock is behind, or because a CA backdates nothing while your VM is minutes slow — the browser shows the same date-invalid error even though nothing has expired. Reading both dates rather than just notAfter catches this immediately.

Cause 3: the server is presenting a different certificate

This is the cause that survives the longest, because everything looks correct when you test the wrong thing. If the client resolves the hostname to a different IP than you do, or connects without SNI, it gets a different certificate — often an old default vhost certificate that expired months ago and that nobody noticed because no one visits it deliberately.

# With SNI — what a modern browser sees
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -subject -dates

# Without SNI — what the default vhost serves
echo | openssl s_client -connect example.com:443 2>/dev/null \
  | openssl x509 -noout -subject -dates

# Pin the IP, keep the hostname — test one backend at a time
echo | openssl s_client -connect 203.0.113.10:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -subject -dates
Test with and without SNI, and per-IP

If the two differ, work through this list:

  • Multiple A records or a stale one. One backend behind a round-robin is serving an old certificate. Enumerate them with the A Record Lookup and test each IP with the -connect IP -servername host form above.
  • The user resolves the name differently than you do. A stale cache, a split-horizon resolver, or a hosts-file entry sends them somewhere else entirely. Compare answers across resolvers with DNS Compare and worldwide with the propagation checker.
  • A vhost is missing its certificate directive. Requests for a hostname with no matching server_name fall through to the default block. Every hostname on the IP needs its own configuration.
  • TLS terminates at a CDN or load balancer. The certificate you renewed on the origin is not the one the public sees. Confirm where TLS terminates by checking response headers with the HTTP Headers Checker.
  • The name is not on the certificate at all. A hostname missing from the SAN list produces ERR_CERT_COMMON_NAME_INVALID rather than a date error, but the two get reported interchangeably by users. Read the SAN list with openssl x509 -noout -ext subjectAltName.

What if the dates are fine and it still fails?

Then the error you are looking at is probably not really a date error. Browsers surface several distinct failures through a similar interstitial, and the exact code matters:

Chrome errorWhat it meansWhere to look
ERR_CERT_DATE_INVALIDToday is outside notBefore/notAfter per the client clockCertificate dates, or the device clock
ERR_CERT_AUTHORITY_INVALIDNo path to a trusted root could be builtIncomplete chain
ERR_CERT_COMMON_NAME_INVALIDHostname is not in the certificate's SAN listSAN list, wrong vhost
ERR_SSL_PROTOCOL_ERRORHandshake failed before certificate validationTLS version, cipher config, or a middlebox
NET::ERR_CERT_REVOKEDThe certificate was revoked by the CAReissue; check for a key compromise

One more possibility worth ruling out: TLS interception. Corporate proxies and endpoint security products reissue every certificate on the fly with their own CA. If a single user's browser shows an issuer you do not recognise and dates you never set, you are looking at their inspection appliance, not your server. Ask them for the issuer name shown in the certificate viewer.

Once the site is healthy again, set up an expiry alert so the next one never reaches a user — the scripts in Check SSL Expiry with OpenSSL take about ten minutes to put into cron.

Frequently asked questions

Only one user gets ERR_CERT_DATE_INVALID. Is my certificate broken?
Very unlikely. If the certificate were expired, everyone would see it. A single affected device almost always has a wrong system clock or is resolving your hostname to a different IP. Ask whether other HTTPS sites also fail on that device — if they do, it is the clock.
My certificate renewed successfully but the browser still shows the old expiry. Why?
The web server is still serving the old certificate from memory. Reload nginx or Apache after renewal — a new file on disk has no effect until the process re-reads it. Compare the on-disk dates with what openssl s_client reports to confirm.
Can a certificate be "not yet valid"?
Yes, and it produces the same browser error. If notBefore is in the future relative to the client, validation fails exactly as it does for an expired certificate. This usually means the client clock is behind rather than that the certificate is wrong, so always read both dates rather than just notAfter.
Is it safe to click through the warning?
Only when you have already established from the command line that the certificate is genuinely fine and the local clock is the problem. Clicking through means you are accepting an unvalidated identity, so never advise a customer to do it as a fix — fix the clock or the server instead.
Why does curl succeed while the browser fails, or vice versa?
They may not be talking to the same server or using the same trust decisions. curl follows your resolver and your CA bundle; a browser may use the OS trust store, a corporate proxy CA, or a cached HSTS entry that forces HTTPS. Pin the IP with -connect IP -servername host to remove resolution differences from the comparison.
Does an expired intermediate cause ERR_CERT_DATE_INVALID?
It can, though browsers more often report it as an authority problem. openssl s_client evaluates the entire path, so check the "Verify return code" line rather than only the leaf dates — code 10 with a valid-looking leaf points at something further up the chain.

Last updated: 2026-09-01