Debug guide · you're seeing
NET::ERR_CERT_DATE_INVALIDYour connection is not privateSEC_ERROR_EXPIRED_CERTIFICATESEC_ERROR_EXPIRED_ISSUER_CERTIFICATESSL certificate problem: certificate has expiredCERT_HAS_EXPIRED
ERR_CERT_DATE_INVALID: Expired Certificates and Fixes
Fix NET::ERR_CERT_DATE_INVALID by checking certificate dates, client clocks, failed renewals, stale nginx deployments and expired intermediate certificates.
On this page
- What it means
- Who sent it?
- Fix it, in order of evidence
- 1. The leaf expired and renewal never completed
- 2. Renewal succeeded, but the endpoint serves the old certificate
- 3. An intermediate expired
- 4. The client clock is wrong, or validity has not started
- Shorter lifetimes change the renewal budget
- Reproduce and verify
- Related
TL;DR: The client thinks a certificate is outside its validity dates. Check the certificate the hostname actually serves, then compare it with the renewed file. If the file is new but the endpoint is old, fix deployment or reload nginx. If the leaf dates are fine, inspect the intermediates and the client clock. A successful renewal job does not prove users received the renewed certificate.
What it means
Chrome can show Your connection is not private with NET::ERR_CERT_DATE_INVALID. Its error definition covers both expiry and a certificate whose validity has not started, as judged by the client clock.
Certificates carry notBefore and notAfter. RFC 5280 Section 4.1.2.5 defines that interval; Section 6.1.3 checks validity during path validation. The error is a TLS certificate validation failure, before the client can exchange an HTTP request with that endpoint. It is not an HTTP status code.
Other clients expose these exact strings:
- Firefox:
SEC_ERROR_EXPIRED_CERTIFICATEfor an expired peer certificate, andSEC_ERROR_EXPIRED_ISSUER_CERTIFICATEfor an expired issuer certificate, as defined in Mozilla NSS. - curl with OpenSSL:
SSL certificate problem: certificate has expired. The curl backend combines its prefix with OpenSSL’s verification error. Other TLS backends can phrase the message differently. - Node.js:
CERT_HAS_EXPIRED. A futurenotBeforeinstead maps toCERT_NOT_YET_VALID.
Who sent it?
The client reports the failure; the certificate comes from the TLS terminator it reached. That might be nginx, an ingress controller, a load balancer or a CDN. Start with the public hostname, not a certificate file on your origin:
openssl s_client -connect example.com:443 -servername example.com </dev/null \
| openssl x509 -noout -dates -issuer -subject
date -u
Replace example.com with the failing hostname. -servername sends SNI so you inspect that hostname’s certificate. The pipeline prints the leaf certificate’s dates, not every certificate in the chain. It also does not prove validation succeeded: s_client normally continues after verification errors. Read its diagnostics, and use curl without -k for a client check.
Interpret the result against the correct current UTC time:
- Past
notAfter: the certificate has expired. - Future
notBefore: it is not yet valid. - Dates contain the correct time, but the failing device’s time falls outside them: fix that device’s clock and time synchronization.
Fix it, in order of evidence
1. The leaf expired and renewal never completed
With Certbot, inspect the local inventory and scheduler:
sudo certbot certificates
systemctl list-timers --all
sudo certbot renew --dry-run
Check when the renewal task last ran and read its logs. Timer names depend on how Certbot was installed; its documentation tells you to check systemd timers or cron for certbot renew. A dry run exercises renewal against a test server. It does not replace the production certificate.
For cert-manager, replace the namespace and Certificate name:
kubectl -n web describe certificate example-com
kubectl -n web get certificaterequests,orders,challenges
# Describe the pending Challenge using the name from the preceding command
kubectl -n web describe challenge CHALLENGE_NAME
Read the Certificate’s Ready condition, Reason, Message, expiry and renewal time, plus its events. Ready: False is a reason to follow the CertificateRequest → Order → Challenge trail. Check the failed challenge rather than repeatedly recreating the Certificate: cert-manager documents HTTP-01 reachability and DNS-01 propagation checks. Ready: True concerns the certificate in the target Secret; still inspect what the ingress serves.
2. Renewal succeeded, but the endpoint serves the old certificate
Compare the served leaf with the file nginx is configured to use:
openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem \
-noout -dates -serial -fingerprint -sha256
openssl s_client -connect example.com:443 -servername example.com </dev/null \
| openssl x509 -noout -dates -serial -fingerprint -sha256
sudo nginx -t && sudo nginx -s reload
For ordinary file-based nginx TLS configuration, replacing the file alone does not reload the running configuration. nginx reloads gracefully; if applying the new configuration fails, it keeps the old configuration. Inspect its error log and repeat the live probe after reloading.
If Certbot only obtains certificates and your deployment requires an nginx reload, wire that step into a successful-renewal deploy hook, for example:
sudo certbot renew --deploy-hook 'nginx -t && nginx -s reload'
An installer plugin may already handle the reload. Check your renewal configuration first. Deploy hooks run after successful renewal; ordinary dry runs skip them unless --run-deploy-hooks is supplied.
For a load balancer or CDN, compare the certificate attached to the public TLS listener with the newly issued one. Renewing an origin file cannot update a separate edge certificate. For an ingress, confirm the TLS Secret name and namespace, then check controller logs for reload failures.
Check each address DNS returns; one stale endpoint can make the failure intermittent:
dig +short example.com A
dig +short example.com AAAA
# Repeat for each returned IP, keeping the hostname in the URL
curl --noproxy '*' -v --resolve example.com:443:192.0.2.10 https://example.com/
curl --noproxy '*' -v --resolve 'example.com:443:[2001:db8::10]' https://example.com/
The addresses above are placeholders. --resolve pins the connection address while preserving the hostname for SNI and certificate verification. Skip CNAME lines in dig output. This checks the addresses visible to your resolver, not every backend behind a load balancer or every CDN location. Probe known TLS-serving nodes separately and repeat from an affected network.
3. An intermediate expired
Do not stop at a valid leaf. Inspect the served chain:
openssl s_client -connect example.com:443 -servername example.com -showcerts </dev/null
Copy each PEM certificate block into a separate file, then inspect it:
openssl x509 -in intermediate.pem -noout -dates -issuer -subject
-showcerts lists what the server sent, not a verified chain. OpenSSL diagnostics identify the failing depth; depth 0 is the leaf. An expiry at a higher depth points beyond the leaf. Install the current intermediate chain supplied by your CA and reload the terminator. For Certbot-managed nginx, use fullchain.pem for ssl_certificate; it contains the leaf followed by intermediates.
4. The client clock is wrong, or validity has not started
Compare the failing device’s clock with a correctly synchronized machine. Mozilla’s time-related error guide covers both expired and not-yet-valid certificates. Enable automatic date/time synchronization on the affected device, then retry.
If the client time is correct and notBefore is in the future, deploy a currently valid certificate or ask the issuer to correct issuance. Changing the client’s clock to accommodate a bad certificate hides the fault. Keep certificate verification enabled while checking the repair.
Shorter lifetimes change the renewal budget
The adopted CA/Browser Forum ballot is SC-081v3. Its Section 6.3.2 schedule sets these maximum validity periods for newly issued publicly trusted TLS subscriber certificates:
- Issued March 15, 2026 through March 14, 2027: 200 days.
- Issued March 15, 2027 through March 14, 2029: 100 days.
- Issued on or after March 15, 2029: 47 days.
These are ceilings, not promised lifetimes; a CA can issue shorter certificates. The schedule does not retroactively change an existing certificate’s notAfter and does not govern your private CA.
Treat automated renewal and deployment as an operational requirement. That is the engineering consequence of the shorter schedule, not a claim that the ballot mandates a particular automation tool. Monitor the dates served by the public endpoint so a broken deployment is caught even when issuance succeeds.
Reproduce and verify
After the repair, repeat the leaf and chain inspection and test each known serving address without bypassing verification:
curl --noproxy '*' -v https://example.com/ -o /dev/null
openssl s_client -connect example.com:443 -servername example.com \
-verify_hostname example.com -verify_return_error </dev/null
Confirm the new dates and fingerprint at the endpoint, a successful verification result, and a working request from the previously failing client. One successful request does not clear a stale node you have not tested.
Related
- Certificate name errors: the certificate is for a different hostname.
- ERR_SSL_PROTOCOL_ERROR: the TLS exchange fails before certificate validation can finish.
- HTTPS and TLS: certificates, chains and the handshake.
- ERR_CERT_AUTHORITY_INVALID: the certificate is in date but its issuer is untrusted or an intermediate is missing.
Frequently asked questions
Why does Chrome show NET::ERR_CERT_DATE_INVALID?
A certificate appears expired or not yet valid according to the client clock. Check the certificate served by the actual HTTPS endpoint and compare its notBefore and notAfter dates with the correct current time.
Why is my certificate still expired after Certbot renewed it?
The new certificate may exist on disk while nginx, a load balancer, a CDN or another server in the pool still serves the old one. Compare the live certificate with the renewed file, then deploy or reload it at the TLS terminator.
Can an expired intermediate cause this error when the leaf is valid?
Yes. Certificate path validation checks validity dates along the selected chain. Inspect the served intermediates as well as the leaf and install the current chain supplied by the certificate authority.
Does clearing the browser cache fix an expired certificate?
Clearing the cache does not extend certificate validity. Fix the client clock if it is wrong, or have the site operator renew and deploy the certificate or chain that failed validation.
When do public TLS certificates become limited to 47 days?
CA/Browser Forum ballot SC-081v3 sets a maximum of 47 days for certificates issued on or after March 15, 2029. The preceding limits are 200 days from March 15, 2026, and 100 days from March 15, 2027; these limits apply to new issuance.
Sources
- MDN: Transport Layer Security (TLS)developer.mozilla.org
- RFC 5280: Certificate validity and path validationrfc-editor.org
- Chromium source: CERT_DATE_INVALIDgithub.com
- Mozilla NSS source: certificate error stringsgithub.com
- Node.js: certificate validity errorsnodejs.org
- curl source: OpenSSL certificate verificationgithub.com
- OpenSSL: s_clientdocs.openssl.org
- OpenSSL: x509docs.openssl.org
- Certbot: renewal and deployment hookseff-certbot.readthedocs.io
- cert-manager: troubleshooting certificate issuancecert-manager.io
- nginx: reload behaviournginx.org
- CA/Browser Forum: adopted SC-081v3 ballotcabforum.org
- SC-081v3 requirements: Section 6.3.2 lifetime schedulecabforum.org
Related
NET::ERR_CERT_COMMON_NAME_INVALID: Fix the Name Mismatch
Fix NET::ERR_CERT_COMMON_NAME_INVALID and related ERR_CERT errors: SAN vs CN, wildcard limits, missing SNI, expired or incomplete chains, with openssl checks.
ERR_SSL_PROTOCOL_ERROR: Causes and Fixes in Chrome
Fix ERR_SSL_PROTOCOL_ERROR: plain HTTP on port 443, TLS version mismatches, SNI, TLS-inspecting proxies and Cloudflare, with curl and openssl checks.
HTTPS Explained: How TLS Secures HTTP
HTTPS is HTTP over TLS. What the TLS handshake does, how certificates prove identity, what HTTPS hides and what it does not, and how to migrate a site safely.
ERR_CERT_AUTHORITY_INVALID: Chain and CA Trust Fixes
Fix ERR_CERT_AUTHORITY_INVALID by inspecting missing intermediates, private CAs, TLS inspection and the CA stores actually used by curl, Node and Python.