Self-Healing CI: Recovering Clock-Skew TLS / Certificate Failures
A certificate that looks "not yet valid" or "expired" when it is clearly fine is usually the runner’s clock being wrong - fix the time, and TLS succeeds.
The problem
A TLS connection fails with certificate is not yet valid or certificate has expired against a certificate that is perfectly valid. The real cause is clock skew: the runner’s system time drifted, so a valid cert appears outside its validity window. A human re-syncs the clock or re-runs on a freshly-timed runner and it connects unchanged.
x509: certificate has expired or is not yet valid: current time ... is before ...
# or
SSL certificate problem: certificate is not yet validWhy it happens
Certificate validation compares the cert’s validity window against the local system clock. If the runner’s clock is skewed - drifted, unsynced after a fresh boot, or wrong by hours - a valid certificate falls outside the perceived window and TLS is rejected.
The certificate is fine; the clock is wrong. Once the runner’s time is corrected (NTP sync), the same connection validates with no change to the cert or the endpoint.
The manual fix
The manual fix is to correct the runner clock, then retry:
- Check the system time against a trusted source and confirm the skew.
- Force a time sync (NTP) so the clock is accurate.
- Re-run the job - TLS validation now sees the correct current time.
date -u
sudo chronyc makestep || sudo ntpdate -u pool.ntp.org
date -uHow this gets automated
A clock-skew TLS failure has a recognizable signature - a validity-window error against a known-good cert - and a well-defined remedy: correct the time and retry. A self-healing CI pipeline detects the skew-driven failure, corrects the runner’s clock, retries the step, and only escalates if the certificate is genuinely outside its window after the clock is right.
Frequently asked questions
How do I know it is clock skew and not a real expired certificate?
date -u output to a trusted time source and read the error’s "current time" against the cert’s validity window. If the runner’s clock is wrong, a perfectly valid cert looks expired or not-yet-valid - correcting the time resolves it, which is exactly what self-healing does automatically.