prometheus/node_exporter · error
only IP address of local NTP server is valid for…
Error message
only IP address of local NTP server is valid for --collector.ntp.server
What it means
NewNtpCollector validates the --collector.ntp.server flag before creating the collector. Unless --collector.ntp.server-is-mine is set, the value must parse as an IP address (net.ParseIP non-nil) and be a loopback address. Hostnames, non-loopback IPs, or arbitrary strings are rejected with this error at startup.
Solutions
- Resolve your local NTP server's address and pass it as an IP literal, e.g. --collector.ntp.server=127.0.0.1.
- Only if you truly control the server and accept the TTL=1 reachability model, add --collector.ntp.server-is-mine to bypass the loopback check.
- Do not use hostnames or public NTP pools (pool.ntp.org); this collector is not designed for them.
- If you need generic NTP monitoring, use a different exporter (e.g. an NTP exporter based on beevik/ntp) since this collector is deprecated.
Example fix
// before // --collector.ntp.server=pool.ntp.org // after: local server IP, or explicitly claim the server // --collector.ntp.server=192.168.1.1 // --collector.ntp.server-is-mine
Defensive patterns
Strategy: validation
Validate before calling
// shell: validate the flag value before starting the exporter
SRV="$(grep -Po '(?<=--collector\.ntp\.server=)\S+' <<<'...')"
ipcalc "$SRV" >/dev/null 2>&1 || echo "$SRV is not an IP literal"
python3 -c "import ipaddress,sys; a=ipaddress.ip_address('$SRV'); sys.exit(0 if a.is_loopback else 1)" || echo "$SRV is not loopback" Prevention
- Treat --collector.ntp.server as an IP literal only; never pass hostnames.
- Resolve your local NTP server to an IP in config management before templating the flag.
- Use --collector.ntp.server-is-mine only when you control the target server.
- Remember the collector is deprecated; prefer alternative NTP exporters for non-local servers.
When it happens
Trigger: Starting node_exporter with --collector.ntp.server set to a hostname (e.g. pool.ntp.org), an empty value, a non-IP string, or a public/non-loopback IP, while --collector.ntp.server-is-mine is false.
Common situations: Users copying examples that use NTP pool hostnames; pointing the collector at a remote public NTP server instead of a local one (the collector intentionally requires a local server because it uses IP TTL=1 probes); forgetting that the flag takes an IP, not a DNS name.
Understand the failure class
Background: "unknown output mode", "invalid value for flag", "expects true/false": fixing invalid flag value errors in CLI tools — this error's family across 24 libraries.
Related errors
- invalid NTP protocol version
- offset tolerance must be non-negative
- invalid NTP port number
- --collector.diskstats.ignored-devices and…
- device-exclude & device-include are mutually exclusive
AI-assisted analysis of prometheus/node_exporter@17ddd77c59 (2026-09-07).
Data as JSON: /api/errors/bddf6180e6e2136b.
Report an issue: GitHub.
Appendix: source
Thrown at collector/ntp.go:66
)
type ntpCollector struct {
stratum, leap, rtt, offset, reftime, rootDelay, rootDispersion, sanity typedDesc
logger *slog.Logger
}
func init() {
registerCollector("ntp", defaultDisabled, NewNtpCollector)
}
// NewNtpCollector returns a new Collector exposing sanity of local NTP server.
// Default definition of "local" is:
// - collector.ntp.server address is a loopback address (or collector.ntp.server-is-mine flag is turned on)
// - the server is reachable with outgoing IP_TTL = 1
func NewNtpCollector(logger *slog.Logger) (Collector, error) {
ipaddr := net.ParseIP(*ntpServer)
if !*ntpServerIsLocal && (ipaddr == nil || !ipaddr.IsLoopback()) {
return nil, fmt.Errorf("only IP address of local NTP server is valid for --collector.ntp.server")
}
if *ntpProtocolVersion < 2 || *ntpProtocolVersion > 4 {
return nil, fmt.Errorf("invalid NTP protocol version %d; must be 2, 3, or 4", *ntpProtocolVersion)
}
if *ntpOffsetTolerance < 0 {
return nil, fmt.Errorf("offset tolerance must be non-negative")
}
if *ntpServerPort < 1 || *ntpServerPort > 65535 {
return nil, fmt.Errorf("invalid NTP port number %d; must be between 1 and 65535 inclusive", *ntpServerPort)
}
logger.Warn("This collector is deprecated and will be removed in the next major version release.")
return &ntpCollector{
stratum: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(namespace, ntpSubsystem, "stratum"),View on GitHub (pinned to 17ddd77c59)