prometheus/node_exporter · error

failed to retrieve adjtimex stats

Error message

failed to retrieve adjtimex stats: %w

What it means

The timex collector calls unix.Adjtimex to read kernel time-sync status. If the syscall returns an error other than EPERM (which is downgraded to ErrNoData), it is wrapped as 'failed to retrieve adjtimex stats: %w'. Note the error may also surface through the ErrNoData path when permission is denied, so callers see either this error or a no-data skip.

Solutions

  1. Grant the process CAP_SYS_TIME (setcap cap_sys_time+ep) if EPERM-related behavior is desired, or run as root.
  2. Inspect the wrapped errno to determine the real cause (EFAULT, EINVAL, etc.).
  3. If seccomp/container policies block adjtimex, relax the policy or disable the timex collector.
  4. Accept ErrNoData semantics: permission-denied intentionally skips collection.
Defensive patterns

Strategy: try-catch

Validate before calling

// check effective capabilities before enabling timex collection
// e.g. run as root or with cap_sys_time; capsh --print | grep cap_sys_time

Try / catch

if err := c.Update(ch); err != nil {
    if errors.Is(err, ErrNoData) {
        return // permission denied was downgraded; collection intentionally skipped
    }
    if strings.Contains(err.Error(), "failed to retrieve adjtimex stats") {
        logger.Warn("timex unavailable", "err", err)
        return
    }
    return err
}

Prevention

When it happens

Trigger: timexCollector.Update when unix.Adjtimex(timex) fails with a non-EPERM errno (e.g. EFAULT from a bad buffer, or other kernel errors); with EPERM the collector logs a debug and returns ErrNoData instead.

Common situations: Running the exporter as a non-root user without the CAP_SYS_TIME capability in environments that restrict adjtimex (some hardened kernels/seccomp profiles block the syscall entirely, producing non-EPERM errors).

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of prometheus/node_exporter@17ddd77c59 (2026-09-07). Data as JSON: /api/errors/5e75dcf007266678. Report an issue: GitHub.

Appendix: source

Thrown at collector/timex.go:174

			"Is clock synchronized to a reliable server (1 = yes, 0 = no).",
			nil, nil,
		), prometheus.GaugeValue},
		logger: logger,
	}, nil
}

func (c *timexCollector) Update(ch chan<- prometheus.Metric) error {
	var syncStatus float64
	var divisor float64
	var timex = new(unix.Timex)

	status, err := unix.Adjtimex(timex)
	if err != nil {
		if errors.Is(err, os.ErrPermission) {
			c.logger.Debug("Not collecting timex metrics", "err", err)
			return ErrNoData
		}
		return fmt.Errorf("failed to retrieve adjtimex stats: %w", err)
	}

	if status == timeError {
		syncStatus = 0
	} else {
		syncStatus = 1
	}
	if (timex.Status & staNano) != 0 {
		divisor = nanoSeconds
	} else {
		divisor = microSeconds
	}

	ch <- c.syncStatus.mustNewConstMetric(syncStatus)
	ch <- c.offset.mustNewConstMetric(float64(timex.Offset) / divisor)
	ch <- c.freq.mustNewConstMetric(1 + float64(timex.Freq)/ppm16frac)
	ch <- c.maxerror.mustNewConstMetric(float64(timex.Maxerror) / microSeconds)
	ch <- c.esterror.mustNewConstMetric(float64(timex.Esterror) / microSeconds)

View on GitHub (pinned to 17ddd77c59)