kubectl "x509: certificate has expired or is not yet valid" in CI
TLS verification failed on time, not trust. Either the client certificate or cluster CA in kubeconfig has actually expired, or the runner’s clock is wrong enough that a currently-valid certificate reads as expired or not-yet-valid.
What this error means
kubectl fails with Unable to connect to the server: x509: certificate has expired or is not yet valid: current time ... is after .... The message includes the validity window and the current time, which tells you whether it is a real expiry or a clock problem.
Unable to connect to the server: x509: certificate has expired or is not yet
valid: current time 2026-06-25T10:00:00Z is after 2026-05-01T00:00:00ZCommon causes
Expired client certificate or cluster CA
A long-lived client cert (or the cluster CA) reached its notAfter date. kubeconfigs that embed certs rather than short-lived tokens eventually expire.
Runner clock skew
If the runner clock is far off (common on fresh/containerized runners without NTP), a valid certificate appears expired or "not yet valid".
How to fix it
Compare the cert window to the runner clock
The message shows both. If the current time is wrong, fix the clock; if the cert is genuinely past notAfter, re-issue it.
date -u
kubectl config view --minify --raw -o jsonpath='{.users[0].user.client-certificate-data}' \
| base64 -d | openssl x509 -noout -datesRenew credentials or fix time
- Re-generate kubeconfig (cloud CLI) or rotate the client certificate that expired.
- Prefer short-lived exec/token auth over embedded long-lived client certs.
- If the clock is skewed, sync it (NTP) so valid certs verify correctly.
How to prevent it
- Use short-lived token/exec auth instead of long-lived embedded client certs.
- Ensure CI runners have correct time (NTP) to avoid false expiry.
- Track cert/CA expiry and rotate before
notAfter.