prometheus/node_exporter · error

couldn't get SNTP reply

Error message

couldn't get SNTP reply: %w

What it means

The ntp collector's Update performs an SNTP query against the configured local NTP server (with the configured protocol version, IP TTL, and 1-second timeout). Any failure — network unreachable, TTL exceeded, timeout, or malformed reply — is wrapped in this message. Because Update errors surface as scrape failures, an unreachable server makes every scrape of this collector fail.

Solutions

  1. Verify a local NTP server is listening: 'chronyc statistics' / 'ss -ulpn | grep 123' and 'ntpdate -q 127.0.0.1'.
  2. Ensure the configured server is directly reachable at IP TTL=1 (same subnet/loopback); otherwise fix topology or (if you own the server) reconsider placement.
  3. Check firewall rules allow outbound UDP 123 and inbound replies.
  4. Point --collector.ntp.server at the correct local server IP.
  5. If NTP checks are not needed, disable with --collector.ntp or --disable-collector.ntp to stop scrape errors.

Example fix

// before: no local NTP server on 127.0.0.1
//   --collector.ntp.server=127.0.0.1  -> scrape error every interval
// after: run chrony/ntpd locally or disable the collector
//   chronyd  (allow 127.0.0.1)
// or
//   --disable-collector.ntp
Defensive patterns

Strategy: retry

Validate before calling

// shell: verify the local NTP server answers before enabling the collector
chronyc -a 'tracker' >/dev/null 2>&1 || ntpq -c rv 127.0.0.1 >/dev/null 2>&1 || echo "no local NTP server on $NTP_SERVER"

Try / catch

// handle transient query failures without failing every scrape
if err := query(&resp); err != nil {
    if isTimeout(err) || isRefused(err) {
        c.logger.Warn("ntp query failed, will retry next scrape", "err", err)
        return ErrNoData // degrade gracefully instead of erroring
    }
    return fmt.Errorf("couldn't get SNTP reply: %w", err)
}

Prevention

When it happens

Trigger: cgetQuery/ntp query returns an error during Update: the configured loopback/local NTP server is not running (UDP port closed), a firewall drops the reply, IP_TTL=1 is too low for a non-directly-connected server, or the 1-second timeout expires.

Common situations: Enabling --collector.ntp on hosts without a local ntpd/chronyd listening; pointing at a loopback IP where nothing listens on port 123 (connection refused/ICMP port unreachable); placing the exporter more than one hop from the server so TTL=1 probes never arrive; transient network loss during a scrape.

Related errors


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

Appendix: source

Thrown at collector/ntp.go:135

		), prometheus.GaugeValue},
		sanity: typedDesc{prometheus.NewDesc(
			prometheus.BuildFQName(namespace, ntpSubsystem, "sanity"),
			"NTPD sanity according to RFC5905 heuristics and configured limits.",
			nil, nil,
		), prometheus.GaugeValue},
		logger: logger,
	}, nil
}

func (c *ntpCollector) Update(ch chan<- prometheus.Metric) error {
	resp, err := ntp.QueryWithOptions(*ntpServer, ntp.QueryOptions{
		Version: *ntpProtocolVersion,
		TTL:     *ntpIPTTL,
		Timeout: time.Second, // default `ntpdate` timeout
		Port:    *ntpServerPort,
	})
	if err != nil {
		return fmt.Errorf("couldn't get SNTP reply: %w", err)
	}

	ch <- c.stratum.mustNewConstMetric(float64(resp.Stratum))
	ch <- c.leap.mustNewConstMetric(float64(resp.Leap))
	ch <- c.rtt.mustNewConstMetric(resp.RTT.Seconds())
	ch <- c.offset.mustNewConstMetric(resp.ClockOffset.Seconds())
	if resp.ReferenceTime.Unix() > 0 {
		// Go Zero is   0001-01-01 00:00:00 UTC
		// NTP Zero is  1900-01-01 00:00:00 UTC
		// UNIX Zero is 1970-01-01 00:00:00 UTC
		// so let's keep ALL ancient `reftime` values as zero
		ch <- c.reftime.mustNewConstMetric(float64(resp.ReferenceTime.UnixNano()) / 1e9)
	} else {
		ch <- c.reftime.mustNewConstMetric(0)
	}
	ch <- c.rootDelay.mustNewConstMetric(resp.RootDelay.Seconds())
	ch <- c.rootDispersion.mustNewConstMetric(resp.RootDispersion.Seconds())

View on GitHub (pinned to 17ddd77c59)