<!-- https://pkizerotohero.com/errors/openssl-certificate-has-expired/ | Markdown mirror of the HTML page | PKI Zero to Hero, by Duyutech BV -->

> Fix OpenSSL verify error 10, certificate has expired: find which certificate expired, renew and reload it, or correct a wrong clock.

Source: https://pkizerotohero.com/errors/openssl-certificate-has-expired/ · Last reviewed: 2026-10-20

- OpenSSL
- Exact text checked with the real tool

# verify error:num=10:certificate has expired

Also seen in: curl, git, Python, Node.js (CERT\_HAS\_EXPIRED), npm

**In one sentence:**

A certificate in the chain is past its notAfter date: usually the server's certificate was not renewed or the renewed one never loaded; sometimes the client's clock is wrong.

[Check yours: Certificate decoder](https://pkizerotohero.com/tools/decoder/)

## Where you see it

In `openssl s_client` output, and in every tool built on OpenSSL. The code is `X509_V_ERR_CERT_HAS_EXPIRED` in the [OpenSSL verification options documentation](https://docs.openssl.org/3.0/man1/openssl-verification-options/).

```text
$ openssl s_client -connect www.example.com:443 -servername www.example.com </dev/null
Connecting to 192.0.2.30
CONNECTED(000001C4)
depth=2 O=Example CA, CN=Example Root CA
verify return:1
depth=1 O=Example CA, CN=Example Issuing CA
verify return:1
depth=0 CN=www.example.com
verify error:num=10:certificate has expired
notAfter=Apr  1 00:00:00 2026 GMT
verify return:1
...
Verification error: certificate has expired
Verify return code: 10 (certificate has expired)
```

Other tools show the same text: curl and git print `SSL certificate problem: certificate has expired`, Python prints `certificate verify failed: certificate has expired`, and Node.js and npm report `CERT_HAS_EXPIRED`.

## What it means

Every certificate has a [validity period](https://pkizerotohero.com/handbook/glossary/#validity-period): a `notBefore` and a `notAfter` date. Clients compare those dates with their own clock. At the depth shown (`depth=0` is the server’s own certificate, `depth=1` the intermediate above it), the current time is past `notAfter`, so the certificate can no longer be relied on, even if everything else is correct.

## Likely causes

### The server’s certificate expired

**Confirm** what the server is serving right now:

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

```text
subject=CN=www.example.com
notBefore=Jan  1 00:00:00 2026 GMT
notAfter=Apr  1 00:00:00 2026 GMT
```

**Fix:** renew the certificate with your CA or ACME client, install it with its full chain, and reload the server. With certbot and nginx, for example:

```bash
sudo certbot renew
sudo nginx -t && sudo systemctl reload nginx
```

### It was renewed, but the server still serves the old one

Common after a manual renewal or a failed reload hook. Compare the file on disk with what the server sends:

```bash
openssl x509 -in /etc/ssl/www.example.com/fullchain.pem -noout -enddate
```

If the file is newer than what `s_client` shows, reload or restart the service. Behind a load balancer, test each backend directly, because one node may still have the old certificate:

```bash
openssl s_client -connect 192.0.2.31:443 -servername www.example.com </dev/null 2>/dev/null | openssl x509 -noout -enddate
```

Also check where TLS actually ends: a load balancer, CDN or ingress controller may hold its own copy of the certificate.

### An intermediate in the chain expired

If the error shows `depth=1` or higher, the server’s certificate is fine but it is sent with an outdated intermediate. Download the current chain from your CA, rebuild `fullchain.pem` (server certificate first), and reload.

### The client’s clock is wrong

If a certificate that is valid elsewhere fails on one machine, check that machine’s time in UTC:

```bash
date -u
timedatectl status
```

```powershell
w32tm /query /status
```

Turn on time synchronisation (`sudo timedatectl set-ntp true` on systemd Linux, `w32tm /resync` on Windows). A clock that runs behind gives the opposite error: `verify error:num=9:certificate is not yet valid`.

### An old client builds an outdated path

Very old OpenSSL versions and stale CA bundles can pick a path through an expired root or cross-signed certificate even when a valid path exists. Update the CA bundle and the TLS library on the client.

Note

Test a date in advance

`openssl verify -attime` checks a chain at a moment you choose, given as seconds since 1970. Use it to see whether a new chain will still verify after a planned date.

Warning

Do not ignore expiry

Disabling verification, or tools’ options to skip time checks, turn an outage you can see into a weakness you cannot. Renew and automate instead.

Lifetimes are getting shorter: public TLS certificates may be valid for at most 200 days since 15 March 2026, and for at most 47 days from 15 March 2029. Manual renewal will not keep up, so automate it, for example with ACME, and monitor what each endpoint actually serves.

## Check yours

*Interactive tool: Certificate decoder (runs in the browser at [/tools/decoder/](https://pkizerotohero.com/tools/decoder/))*

Paste the server’s certificate (the first `BEGIN CERTIFICATE` block from `openssl s_client -showcerts`). The decoder shows `notBefore`, `notAfter` and how many days are left or overdue.

## Learn why

- [Anatomy of an X.509 certificate](https://pkizerotohero.com/handbook/x509-certificates/): the validity fields.
- [Inventory, expiry and renewal](https://pkizerotohero.com/handbook/certificate-lifecycle/): how to stop expiry outages.
- [ACME and the 47-day schedule](https://pkizerotohero.com/handbook/acme/): automated renewal.
- Browser version of this error: [NET::ERR\_CERT\_DATE\_INVALID](https://pkizerotohero.com/errors/chrome-err-cert-date-invalid/).
- See also: the same problem in [Node.js](https://pkizerotohero.com/errors/node-cert-has-expired/), [Java](https://pkizerotohero.com/errors/java-certificate-expired/) and [Go and kubectl](https://pkizerotohero.com/errors/go-x509-certificate-expired/).

**Early edition.** Checked against the standards; an independent expert review is in progress. Found a mistake? [Tell us](https://pkizerotohero.com/contact/?topic=content-error&page=/errors/openssl-certificate-has-expired/).

Last reviewed 20 October 2026Edition 0.9

## Learn why it happens

- [Chapter 8: Anatomy of an X.509 certificate](https://pkizerotohero.com/handbook/x509-certificates/)
- [Chapter 19: Inventory, expiry and renewal](https://pkizerotohero.com/handbook/certificate-lifecycle/)

## Fix it step by step

- [How to inspect a certificate with OpenSSL](https://pkizerotohero.com/guides/inspect-certificate-openssl/)
- [How to check when a certificate expires, and monitor it](https://pkizerotohero.com/guides/check-certificate-expiry/)
- [How to build a test CA with OpenSSL (lab only)](https://pkizerotohero.com/guides/openssl-test-ca/)
- [How to prepare for short-lived certificates: a checklist](https://pkizerotohero.com/guides/prepare-47-day-certificates/)

## Everything on this topic

- [Lifecycle and automation](https://pkizerotohero.com/topics/lifecycle-and-automation/)
