• Go
  • Exact text checked with the real tool

x509: certificate has expired or is not yet valid

Also seen in: kubectl, Kubernetes, Docker, Terraform, Helm, Prometheus, other Go programs

In one sentence

A certificate is outside its validity dates by this machine's clock; the end of the message says which. In Kubernetes, the cluster's own certificates have often expired.

Where you see it

In programs written in Go: kubectl and other Kubernetes tools, the Docker client and daemon, Terraform, Helm and your own Go services. A Go HTTP client prints:

Get "https://api.example.com/": tls: failed to verify certificate: x509: certificate has expired or is not yet valid: current time 2026-10-20T02:08:22Z is after 2026-04-01T00:00:00Z

kubectl prints the same reason, first in a few log lines and then as a summary:

E1020 02:08:44.981559    3859 memcache.go:381] "Couldn't get current server API group list" err="Get \"https://203.0.113.10:6443/api?timeout=32s\": tls: failed to verify certificate: x509: certificate has expired or is not yet valid: current time 2026-10-20T02:08:44Z is after 2026-04-01T00:00:00Z"
Unable to connect to the server: tls: failed to verify certificate: x509: certificate has expired or is not yet valid: current time 2026-10-20T02:08:44Z is after 2026-04-01T00:00:00Z

The text comes from Go’s crypto/x509 verify.go. Go 1.20 added the tls: failed to verify certificate: prefix; since Go 1.14 the message ends with the two times. Docker adds its own prefix, such as Error response from daemon:.

What it means

Every certificate has a validity period. Go checks each certificate on the path against the machine’s clock, and the end of the message says what it found:

  • current time … is after …: the certificate expired at the second time shown;
  • current time … is before …: the certificate is not valid yet until the second time, which usually means this machine’s clock is behind.

Compare the first time with the real time. If the first time is wrong, fix the clock; if it is right, renew the certificate.

Likely causes

The server’s certificate expired

Confirm what the server sends:

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

Fix: renew the certificate, install it with its full chain, and reload the service. For a private Docker registry, also check the CA and client certificates in /etc/docker/certs.d/<registry>/ on each client. 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: automate renewal (How to check when a certificate expires, and monitor it).

The Kubernetes cluster’s own certificates expired

Clusters built with kubeadm have their own private CA. “Client certificates generated by kubeadm expire after 1 year”, and kubeadm renews them automatically during control-plane upgrades (Kubernetes documentation). A cluster that was not upgraded for a year stops answering kubectl with exactly this error. Confirm on a control-plane node:

sudo kubeadm certs check-expiration

Fix, following that page: renew on every control-plane node, restart the control-plane static Pods, and copy the new admin kubeconfig:

sudo kubeadm certs renew all
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

To restart a static Pod, move its manifest out of /etc/kubernetes/manifests/, wait about 20 seconds, then move it back. Your own kubeconfig may also hold an expired client certificate if it was copied from admin.conf long ago.

The certificate was renewed, but the old one is still served

Ingress controllers, load balancers and long-running Go services keep the certificate they loaded. Compare the served dates with the new file (openssl x509 -in tls.crt -noout -enddate), then reload or restart. In Kubernetes, check that the ingress uses the renewed Secret; see How to automate certificates in Kubernetes with cert-manager.

The machine’s clock is wrong

is before with a date in the future, or a current time that is clearly wrong, points to the client’s clock. Small devices without a clock battery, virtual machines restored from snapshots and containers on such hosts are typical. Fix: turn on time synchronisation (timedatectl status, then sudo timedatectl set-ntp true on systemd Linux).

Check yours

Try it: Certificate decoderOpen the full tool

Runs in your browser. Nothing you paste is sent anywhere.

PEM text, several PEM blocks, or a .pem, .crt, .cer or .der file (drop it on the box). Certificates are public, so they are safe to paste.

Paste the certificate (for a kubeconfig, decode client-certificate-data with base64 -d). The decoder shows the validity dates and how many days are left or overdue.

Learn why

In the gameLevel 8: The certificateRoyal Notary, Keystone. In development

Early edition. Checked against the standards; an independent expert review is in progress. Found a mistake? Tell us.

Last reviewed Edition 0.9