Skip to main content
Blog|
How-to guides

NET::ERR_CERT_DATE_INVALID: what it means and how to fix it

|
Apr 22, 2026|13 min read
HOW-TO GUIDESNET::ERR_CERT_DATE_INVALID:what it means and how to fixitHOSTNEYhostney.comApril 22, 2026

NET::ERR_CERT_DATE_INVALID is Chrome’s way of saying “the SSL certificate this site presented is not valid right now – either it expired, or your computer thinks the current date is wrong.” Firefox shows SEC_ERROR_EXPIRED_CERTIFICATE . Safari says “This Connection Is Not Private” with a date-based reason. The browser refuses the HTTPS handshake and shows the red warning page.

Unlike most SSL errors, this one has two completely different root causes – one on the server, one on your own device – and picking the wrong fix wastes hours. A sysadmin renewing a certificate that is not actually expired gets nowhere. A visitor resetting their laptop clock when the cert has genuinely lapsed sees the same error from every other visitor too. This guide starts with a 30-second diagnostic to tell which one is happening, then walks through the fix for each.

Is it the server or your device? Quick check#

SymptomMost likely cause
Error shows on this site only, from multiple devices and networksServer: cert is expired
Error shows on many sites at once, only from one deviceClient: device clock is wrong
Error shows only to you, works on your phone over cellularClient: browser cache or HSTS timing mismatch
Error started right after a date rollover (midnight UTC, end of month)Server: auto-renewal failed
You just traveled across time zones or restored a factory deviceClient: clock offset too large

If every device in your house sees the error, it is the server. If only your laptop sees it but your phone loads the site fine, it is your device. This is the single most useful distinction to make before spending time on any fix.

30-second diagnostic#

Check the certificate’s expiry date

Open the site in Chrome, click the Not Secure warning next to the URL, select Certificate is not valid, and look at Valid from / Valid to. If today’s date is past the Valid to date, the certificate is expired and the fix lives on the server.

Command-line alternative:

openssl s_client -connect example.com:443 -servername example.com < /dev/null 2>/dev/null \
  | openssl x509 -noout -dates

Output shows notBefore and notAfter timestamps. If notAfter is in the past, the cert is expired.

Check your device clock

On Windows: Settings > Time & Language > Date & Time. Confirm the time is accurate to within a few minutes and that “Set time automatically” is on. On macOS: System Settings > General > Date & Time. On Linux: timedatectl status – look at Local time and System clock synchronized: yes .

If the cert is valid AND your clock is right, jump to the “both are fine but error persists” section. If either is off, the matching section below is the fix.

Cause 1: certificate genuinely expired (server side)#

SSL certificates have a finite lifetime. Let’s Encrypt certs last 90 days. Commercial certs typically last 12 months. When the notAfter date passes, every browser that visits the site starts refusing the connection.

This should almost never happen in 2026. Every serious host auto-renews certificates 30 days before expiry, leaving a month of buffer to detect and fix a failed renewal. An expired cert in production is almost always a failed auto-renewal that nobody noticed, because whoever was supposed to be monitoring it was not.

Why Let’s Encrypt auto-renewal fails

Let’s Encrypt’s certbot renew (or its equivalent in whatever platform handles certificates for you) runs on a cron schedule, typically twice a day. It checks each cert’s expiry, renews anything within 30 days of expiring, and writes the new cert to disk. The most common reasons this silently fails:

  1. Port 80 blocked on the firewall. Let’s Encrypt’s HTTP-01 challenge validates domain ownership by making a request to http://yourdomain.com/.well-known/acme-challenge/<token> . If port 80 is blocked (because “we only serve HTTPS, why do we need port 80”), the validation fails and the renewal is refused. The renewal attempt just errors out without a loud alarm.
  1. DNS-01 challenge missing record. If you use DNS-based validation (for wildcards or private services), the renewal needs permission to add and remove _acme-challenge TXT records on your domain. An expired API key with your DNS provider, a removed subdomain delegation, or a changed DNS provider without updating credentials all break renewal.
  1. HTTP-01 token path blocked. Your web server must serve /.well-known/acme-challenge/<token> over HTTP. A common mistake: a global redirect rule that forces every HTTP request to HTTPS, including the ACME challenge path. The redirect breaks validation. The fix is to whitelist /.well-known/acme-challenge/ from the HTTP-to-HTTPS redirect. See how to redirect HTTP to HTTPS in nginx for how to do this without breaking renewal.
  1. Rate limit hit. Let’s Encrypt limits how many certificates one domain can be issued in a week (50 per domain, 5 duplicates per week). If a misconfigured script keeps requesting new certificates instead of renewing the existing one, you hit the limit and further renewals are blocked until the window clears. Less common than the others, but catastrophic when it happens during an actual renewal window.
  1. Cron job disabled or broken. Someone disabled the renewal cron during maintenance and forgot to re-enable it. Or the cron user’s PATH was changed and certbot is no longer found. Or systemd renewal timer was disabled to silence a noisy log.
  1. DNS propagation lag. You just moved the domain to a new DNS provider, the ACME challenge goes to the old authoritative nameservers, validation fails against stale records. Usually resolves within hours once propagation finishes, but in the meantime renewal keeps trying and failing.

How to check renewal status on a typical Let’s Encrypt install

# Certbot's view of what is managed and when it expires
certbot certificates

# Dry-run a renewal to see what would happen without consuming rate-limit budget
certbot renew --dry-run

# Actually force a renewal right now (only if dry-run succeeded)
certbot renew --force-renewal

If certificates shows EXPIRED and renew --dry-run fails, the error message from the dry-run usually names the exact problem (port 80 timeout, rate limit exceeded, DNS validation failure, etc.).

How to manually re-issue a cert when auto-renewal is broken

If you need to get the site working right now while you fix the underlying issue:

# Using HTTP-01 challenge (requires port 80 open and document root writable)
certbot certonly --webroot -w /var/www/html -d example.com -d www.example.com

# Or standalone mode (certbot runs its own temporary web server on port 80)
certbot certonly --standalone -d example.com -d www.example.com

Reload nginx or Apache after the cert is written ( nginx -s reload or systemctl reload apache2 ). Browsers that were showing the error start succeeding on the next connection.

For a domain-by-domain walkthrough of setup from scratch, see how to install an SSL certificate.

What about commercial certificates?

Commercial certs (DigiCert, Sectigo, etc.) are not auto-renewed by Let’s Encrypt tooling. They require a separate renewal process through whichever CA issued the original certificate – new CSR, new validation, new cert file to install. The failure mode is almost always “the person who managed the renewal left the company” or “the renewal email went to an alias nobody reads.” The fix is the same process as the initial install, minus the domain validation if you renew with the same account.

Whether a commercial certificate is worth the renewal hassle in 2026 is covered in free vs paid SSL certificates.

Cause 2: device clock is wrong (client side)#

The other half of the error message. A certificate lists a Valid from and Valid to date. The browser compares those dates against the current time, reported by the operating system. If the OS thinks it is March 2015 when it is actually April 2026, every certificate issued since 2015 looks invalid because its notAfter is “before” now.

Why the clock drifts

  • Restored a factory device. Fresh out of box, clock is set to the firmware default (often Jan 1, 1970, or the factory test date). Shows the error on every HTTPS site until the device syncs with an NTP server.
  • Dead CMOS battery on a desktop PC. BIOS clock resets to default every time the machine powers off. On each boot, Windows tries to correct it via NTP, but if the machine is offline for a long boot or the NTP server is blocked, the clock stays wrong until networking comes up.
  • Time zone vs actual time confusion. User manually set the clock to adjust for a time zone difference instead of changing the time zone setting. Now the absolute time is off by N hours, enough to push the browser out of the certificate validity window for a freshly-issued cert.
  • Malware. Some malware deliberately rolls the system clock back to make expired certificates (bundled with the malware) appear valid. If the clock is wildly wrong and you did not set it that way, scan for malware.
  • Virtual machines resumed from a snapshot. Snapshots taken months ago, restored on a modern host. VM thinks it is still the snapshot date until it syncs.

How to fix the clock

Windows 10/11: Right-click the clock in the taskbar > Adjust date and time. Toggle “Set time automatically” off, then back on. Click “Sync now” under “Synchronize your clock.” If the sync fails, check that time.windows.com is reachable (firewalls block it on some corporate networks) and try an alternative server like pool.ntp.org via Control Panel > Clock and Region > Internet Time.

macOS: System Settings > General > Date & Time. Enable “Set time and date automatically.” If the time does not update, pick a different NTP server in the dropdown (“Set date and time automatically” > choose Apple, NIST, or custom).

Linux:

# Quick status check
timedatectl status

# Enable NTP sync
sudo timedatectl set-ntp true

# If that does not work, install and start an NTP client
sudo apt install systemd-timesyncd
sudo systemctl start systemd-timesyncd

iOS: Settings > General > Date & Time > enable “Set Automatically.”

Android: Settings > System > Date & time > enable “Set time automatically.”

iPhone or Android that still fails: toggle airplane mode on and off, which triggers a re-sync with the cellular network’s time service.

After the clock is corrected, close and reopen the browser. The error disappears on the next page load.

Confirm the server cert is actually valid first

Before blaming the client clock, sanity-check the cert from a machine with a known-good clock. Load the site on your phone over cellular (different network, different clock source). If the phone loads the site fine, the server is fine and the laptop clock is the problem. If the phone shows the same error, the server cert is expired.

Both clock and cert are fine, but the error persists#

Rare, but it happens.

Stale HSTS entry with include-subdomains. The browser once saw an HSTS header for the apex domain with includeSubDomains , and the subdomain you are now visiting does not have a valid cert. The browser refuses to even try the connection. Fix: in Chrome, go to chrome://net-internals/#hsts , enter the domain under “Delete domain security policies,” and click Delete. Firefox stores HSTS in SiteSecurityServiceState.txt in the profile directory – close the browser, delete the file, restart.

Browser cached the error page. Chrome specifically caches some SSL errors for a short window. Load the URL in an incognito window to bypass the cache. If incognito loads fine, clear the browsing data for that site (Settings > Privacy and security > Site settings > find the domain > clear data) and the normal window starts working too.

Certificate revoked, not expired. The cert was issued correctly, has a valid date range, but the CA revoked it (because of a compromise, a policy violation, or an earlier misissuance). Browsers that check OCSP or CRL see the revocation and refuse the cert. This produces NET::ERR_CERT_REVOKED in Chrome rather than DATE_INVALID , but the message can be inconsistent across browsers. Check the CA’s certificate status lookup or re-issue the cert to confirm.

Intermediate certificate expired separately. The leaf cert for your domain is valid, but one of the intermediate CA certificates in the chain expired. This usually produces NET::ERR_CERT_AUTHORITY_INVALID , but on some browser/version combinations it surfaces as a date error. Reissuing the leaf cert from the current Let’s Encrypt chain resolves it.

If the error is actually a different SSL problem masquerading as a date issue, the nearby guides usually identify the real cause: NET::ERR_CERT_COMMON_NAME_INVALID for name mismatches, ERR_SSL_PROTOCOL_ERROR for handshake failures, ERR_SSL_VERSION_OR_CIPHER_MISMATCH for protocol-version disagreements.

Common mistakes#

  • Clicking “Advanced > Proceed to site (unsafe)” as a fix. The warning is not the problem; the invalid certificate is the problem. Proceeding through the warning bypasses the entire point of HTTPS for that session. Never do this on a site you will log into or enter payment details on.
  • Installing root certificates from random sources to “fix” the error. Rolling the trust store back to older CAs opens the door to attackers presenting their own certs. The fix always lives at the cert or the clock, never at the trust store.
  • Manually setting the system clock backward to match an expired cert. Seems clever; breaks every other HTTPS site you visit. A certificate issued in 2024 with notBefore: 2024-01-01 will not be accepted by a clock that says 2015.
  • Renewing a certificate that is not actually expired. If the user’s clock is the real problem, reissuing the cert does nothing. Always confirm openssl s_client or a working phone on cellular shows the cert as valid before touching the server.
  • Assuming the renewal cron is running. Check it. systemctl status certbot.timer , crontab -l , or whatever your platform uses. An expired certificate means the automation is not working – just fixing this one cert without fixing the automation guarantees the next expiry is another outage.
  • Not monitoring certificate expiry. Browsers warn users first, not administrators. By the time you hear about the problem from a customer, the site has been down for however many hours since midnight UTC. Set up monitoring that alerts at 14 days before expiry, not 0.
  • Redirecting /.well-known/acme-challenge/ to HTTPS. Breaks Let’s Encrypt HTTP-01 validation silently. The renewal fails, nothing alerts, the cert eventually expires, everyone gets the error at once. The challenge path has to stay reachable over HTTP.

How Hostney handles certificate expiry#

Hostney issues Let’s Encrypt certificates for every domain added to a site, and the renewal runs automatically on a platform-managed schedule. The renewals happen well before the 30-day expiry window, and failures surface in the control panel rather than going silent. If a renewal fails, the platform flags the domain and retries – the common failure modes (port 80 blocked at the edge, DNS pointing to a different server, /.well-known/acme-challenge/ path broken by a custom rewrite rule) are reported inline where you can see them and fix them.

Because certificates are managed at the platform level, the typical single-server failure modes are out of the picture by design: port 80 is never closed, the ACME challenge path is never in a custom redirect, and the renewal cron is not something you have to own. The “my cert expired because my certbot cron was broken” class of incident does not apply here.

For domains where you bring your own certificate (less common, but supported for EV or compliance reasons), the platform tracks expiry dates for uploaded certs the same way and warns in advance – a commercial cert still has to be renewed manually, but the 14-day warning gives you time to act before browsers start showing the red page to your visitors.

To check any cert’s current status without logging into anything, the SiteProbe SSL checker shows the notBefore and notAfter dates along with the issuing CA and full chain. Useful as a sanity-check when a customer reports an error and you are not sure whether it is the server or their device.

Summary#

NET::ERR_CERT_DATE_INVALID means the current time falls outside the certificate’s valid date range – either the cert expired, or the device’s clock is wrong. Check which one before fixing either. If the same error hits multiple devices on multiple networks, the cert is expired and the fix is on the server – most often a silently broken Let’s Encrypt auto-renewal (port 80 blocked, ACME challenge path redirected to HTTPS, rate limit exceeded, cron disabled). If the error only hits one device, the clock is wrong – re-sync NTP on that device and the browser starts working immediately. If both appear fine but the error persists, suspect stale HSTS, a cached error page, or a different SSL problem surfacing as a date error. Do not click through the warning, do not set your clock backward to “match” the cert, and do not skip the step of confirming the cert is actually expired before renewing it.

Related articles