Error message
curl: (60) SSL certificate problem: certificate has expired
Also printed as
- curl: (60) SSL certificate OpenSSL verify result: certificate has expired (10)
The reason text is identical in OpenSSL 1.1.1, 3.0 and 3.5 builds of curl. Newer curl releases (8.22.0 in our test) word it "SSL certificate OpenSSL verify result: certificate has expired (10)". Certificates that are not valid yet produce a different reason: "certificate is not yet valid".
curl (OpenSSL backend) — CURLE_PEER_FAILED_VERIFICATION, X509_V_ERR_CERT_HAS_EXPIRED (10)
What it means
One certificate in the chain curl built has a notAfter date earlier than the current time on the machine running curl. It is usually the server's own certificate, but an expired intermediate or cross-signed root produces the same text. The check is done against the local clock, so a wrong clock looks exactly like an expired certificate.
Why it happens
Automatic renewal stopped working
commoncertbot timers that were never enabled, ACME challenges that now fail behind a CDN or firewall, a DNS API token that expired, or a manual process that nobody owns. Public certificate lifetimes are shrinking to 200 days in 2026 and 47 days by 2029, so silent renewal failures surface quickly.
The certificate was renewed but the server still serves the old one
commonnginx, HAProxy, Postfix and Java servers load the certificate at start-up. A renewed file on disk changes nothing until the process reloads; load balancers and CDNs keep their own uploaded copy.
An intermediate or cross-sign in the served chain expired
occasionalA server that bundles an old intermediate (for example a cross-signed one copied from an outdated fullchain) can make clients build a path through an expired certificate even though the leaf is current. The 2021 expiry of the DST Root CA X3 cross-sign broke many older clients this way.
The client's clock is wrong
occasionalDevices without a battery-backed clock, VMs restored from snapshots and containers on a drifting host can be months off. If every HTTPS site fails at once, check the date before anything else.
An old client builds the path to a root that has expired
rareClients with an outdated CA bundle may only know an expired version of a root and fail even though modern clients choose a newer path. Updating ca-certificates fixes them.
How to fix it
- 1.
Find which certificate expired
Print the notAfter date of every certificate the server sends. If the leaf is expired, renew it; if an intermediate is, replace the chain file with the one your CA currently publishes.
bash # Split the served chain into cert1.pem (leaf), cert2.pem, ... and print each expiry date openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null 2>/dev/null \ | awk '/BEGIN CERT/{n++; f="cert" n ".pem"} /BEGIN CERT/,/END CERT/{print > f}' for f in cert*.pem; do openssl x509 -in "$f" -noout -subject -enddate; done - 2.
Renew, reload, and check what is actually served
After renewing, reload every process and device that terminates TLS for the name, then confirm the date from the network side rather than from the file on disk.
bash sudo certbot renew # or your ACME client / CA portal sudo systemctl reload nginx # the server keeps serving the old file until reloaded echo | openssl s_client -connect api.example.com:443 -servername api.example.com 2>/dev/null \ | openssl x509 -noout -enddate # confirm the new date is what the network sees - 3.
Correct the client's clock
When the certificate is fine for other machines, synchronise the failing machine's time with NTP. In containers the clock comes from the host, so fix it there.
bash date -u # compare with the real UTC time timedatectl status # "System clock synchronized: yes"? sudo timedatectl set-ntp true - 4.
Update the client's CA bundle
On long-lived systems, an updated ca-certificates package removes retired roots and adds current ones, which lets OpenSSL pick a valid path instead of an expired one.
bash # Old clients: refresh the root store so they stop building paths through retired roots sudo apt-get update && sudo apt-get install --only-upgrade ca-certificates # Debian/Ubuntu sudo dnf upgrade ca-certificates # RHEL/Fedora
Related errors
verify error:num=10:certificate has expiredOpenSSL CLI (openssl s_client / openssl verify)x509: certificate has expired or is not yet valid: current time 2026-08-20T15:4…Go crypto/x509certificate has expiredNode.js tls / https / fetch[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has exp…Python ssl module (OpenSSL)curl: (60) SSL certificate problem: unable to get local issuer certificatecurl (OpenSSL backend)