k3s-io/k3s · warning

encryption reload time is incorrectly ahead of current time

Error message

encryption reload time is incorrectly ahead of current time

What it means

Before relying on encryption-config reload telemetry, the code reads the apiserver's last-reload unix timestamp from its metrics and sanity-checks it against the local clock. If the metric value is in the future relative to time.Now().Unix(), the check fails: the metric cannot be trusted to order events, usually due to clock skew between the local node and the apiserver's view of time.

Solutions

  1. Synchronize clocks on all involved nodes (systemctl restart chronyd / systemd-timesyncd; verify with timedatectl and cross-node date comparison).
  2. Wait for the next encryption-config reload or metric refresh and retry - once local time passes the metric value the check succeeds.
  3. For VM environments, disable RTC passthrough quirks or use virtio-rtc/PTP sources so guests do not inherit skewed clocks.

Example fix

# before: skewed clocks, validation aborts
date; ssh apiserver-host date  # differ by minutes
# after: sync and retry
sudo systemctl restart chronyd && timedatectl status
k3s secrets-encrypt status  # retry once clocks agree
Defensive patterns

Strategy: retry

Validate before calling

unixUpdateTime := int64(tsMetric.GetMetric()[0].GetGauge().GetValue())
const skewTolerance = 5 // seconds
if time.Now().Unix()+skewTolerance < unixUpdateTime {
    return errors.New("clock skew detected: apiserver reload metric is in the future")
}

Try / catch

if err := wait.Poll(...); err != nil {
    if strings.Contains(err.Error(), "incorrectly ahead of current time") {
        // transient clock skew: resync NTP and retry after clocks converge
        time.Sleep(time.Minute)
    }
}

Prevention

When it happens

Trigger: NTP steps the observing node's clock backwards after a reload; the apiserver host's clock is ahead of the node running the check (VM live-migration, snapshot restore of a VM, drifted RTC); metric scrape caching serving a stale scrape timestamp paired with a corrected local clock.

Common situations: Cloud VMs restored from snapshots resuming with old clocks; heterogeneous chrony/ntp coverage across nodes; laptops/lab hosts suspended and resumed.

Related errors


AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15). Data as JSON: /api/errors/c8487e2f530d8118. Report an issue: GitHub.

Appendix: source

Thrown at pkg/secretsencrypt/config.go:371

		// First time, no metrics exist, so return zeros
		if tsMetric == nil && totalMetrics == nil && initialMetrics {
			return true, nil
		}

		if tsMetric == nil {
			lastFailure = "encryption config time metric not found"
			return false, nil
		}

		if totalMetrics == nil {
			lastFailure = "encryption config total metric not found"
			return false, nil
		}

		unixUpdateTime = int64(tsMetric.GetMetric()[0].GetGauge().GetValue())
		if time.Now().Unix() < unixUpdateTime {
			return true, errors.New("encryption reload time is incorrectly ahead of current time")
		}

		for _, totalMetric := range totalMetrics.GetMetric() {
			logrus.Debugf("totalMetric: %+v", totalMetric)
			for _, label := range totalMetric.GetLabel() {
				if label.GetName() == "status" && label.GetValue() == "success" {
					reloadSuccessCounter = int64(totalMetric.GetCounter().GetValue())
				}
			}
		}
		return true, nil
	})

	if err != nil {
		err = fmt.Errorf("%w: %s", err, lastFailure)
	}

	return unixUpdateTime, reloadSuccessCounter, err

View on GitHub (pinned to 6ba341e396)