prometheus/node_exporter · error
offset tolerance must be non-negative
Error message
offset tolerance must be non-negative
What it means
NewNtpCollector requires --collector.ntp.offset-tolerance to be non-negative. The tolerance is used to judge measured clock offset against the local clock; a negative value is meaningless for this check, so the constructor rejects it with this error at startup.
Solutions
- Set a non-negative duration, e.g. --collector.ntp.offset-tolerance=1ms (the default).
- Search your systemd unit/Docker args/config management for a negative value on this flag.
- If you intended to alert on offset in either direction, the collector already reports signed offset; keep tolerance as the magnitude threshold.
- Fix templates so the value cannot expand to a negative duration.
Example fix
// before // --collector.ntp.offset-tolerance=-1ms // after // --collector.ntp.offset-tolerance=1ms
Defensive patterns
Strategy: validation
Validate before calling
# shell: ensure offset tolerance is a non-negative duration case "$NTP_TOL" in -*) echo "offset-tolerance must be non-negative"; exit 1;; esac
Prevention
- Keep the default (1ms) unless you have a measured reason to change it.
- Guard templates so variables cannot expand to negative durations.
- Understand the flag is a threshold magnitude, not a signed offset.
- Review rendered CLI args in systemd units after config changes.
When it happens
Trigger: Starting node_exporter with --collector.ntp.offset-tolerance set to a negative number, e.g. --collector.ntp.offset-tolerance=-1ms or -0.5 (the flag parses as a time duration, so any negative duration triggers this).
Common situations: Typos where a leading '-' sneaks into the flag value; templated configs where a variable meant to be positive is empty or sign-flipped; misunderstanding the flag as an allowable signed offset rather than a non-negative threshold.
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
- only IP address of local NTP server is valid for…
- invalid NTP protocol version
- 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/2aabdbb1f4302bb0.
Report an issue: GitHub.
Appendix: source
Thrown at collector/ntp.go:74
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"),
"NTPD stratum.",
nil, nil,
), prometheus.GaugeValue},
leap: typedDesc{prometheus.NewDesc(
prometheus.BuildFQName(namespace, ntpSubsystem, "leap"),
"NTPD leap second indicator, 2 bits.",
nil, nil,
), prometheus.GaugeValue},View on GitHub (pinned to 17ddd77c59)