EN FR Home

Stratum 16 Troubleshooting

Fix the NTP "unsynchronized" state on chrony, ntpd and w32tm

1. What stratum 16 really means

In the NTP protocol, the stratum field is an 8-bit integer identifying the distance from the reference atomic clock. Values 1–15 are valid operating strata. Stratum 16 is a sentinel value meaning "unsynchronized" — the daemon has no trusted time source. It is both:

  • the initial state on daemon start-up, before any peer stabilises, and
  • the fallback state when all configured peers become unreachable or are rejected by the sanity checks.

The difference matters for diagnosis. Freshly-booted stratum 16 with a visible iburst countdown is normal. Stratum 16 after 30 minutes of uptime is a fault.

Note that 16 is not "a very bad stratum" on a continuous scale — it sits outside the scale entirely. A stratum 3 clock is synchronized and usable; a stratum 16 clock is not synchronized at all, and the gap between the two is categorical rather than gradual. If that distinction is new to you, the meaning of each stratum level from 0 to 15 is worth reading before you start changing configuration.

2. 3-step diagnostic on chrony and ntpd

Run these three commands in order. Each one points to the most likely next cause.

chrony

$ chronyc tracking          # overall sync status
$ chronyc sources -v        # per-source reachability and selection
$ chronyc sourcestats -v    # offset/jitter stability per source

ntpd / ntpsec

$ ntpq -p                   # per-source table
$ ntpq -c rv                # read variables: stratum, offset, jitter, dispersion
$ ntpq -c 'rv 0 stratum,offset,frequency,sys_jitter'

Read the output against the three common root causes below.

3. Cause #1 — no reachable source

Signature in chronyc sources: every source shows ? or ~ in the selection column, and reach is 0. Signature in ntpq -p: all peers show .INIT. as their refid.

Fix sequence:

# 1. Test UDP 123 reachability
$ nc -u -vz ntp.rdem-systems.com 123
# or, if nc is not UDP-capable
$ ntpdate -q ntp.rdem-systems.com

# 2. Check firewall state
$ sudo iptables -L -n | grep 123
$ sudo firewall-cmd --list-all | grep ntp
$ sudo ufw status | grep 123

# 3. If blocked, open it
$ sudo ufw allow 123/udp           # ufw
$ sudo firewall-cmd --add-service=ntp --permanent && sudo firewall-cmd --reload

Deep dive: the firewall guide covers iptables, firewalld, ufw and Windows Firewall.

4. Cause #2 — offset above the panic threshold

Signature: sources are reachable (reach > 0), but the daemon refuses to step the clock. Logs mention "panic sanity" (ntpd) or "clock jump too large" (chrony).

Default thresholds:

DaemonThresholdDirective
ntpd1000 stinker panic 0 (disable) or launch with -g
chronyConfigurable (no hard panic)makestep 1.0 3 in chrony.conf
w32timeVaries (MaxPosPhaseCorrection / MaxNegPhaseCorrection)Registry under HKLM\SYSTEM\CurrentControlSet\Services\W32Time\Config

Fix — chrony

# One-shot step (manual)
$ sudo chronyc makestep

# Persist: allow step for first 3 clock updates if offset > 1s
# in /etc/chrony/chrony.conf
makestep 1.0 3

Fix — ntpd

# One-shot step at start-up (past panic threshold)
$ sudo systemctl stop ntp
$ sudo ntpd -gq               # query once with -g allowed
$ sudo systemctl start ntp

5. Cause #3 — all sources rejected by selection

Signature: sources are reachable, offsets are small, but the selection column shows x (false ticker) or - (outlyer) on every peer. The daemon has no majority to agree with, so it stays at stratum 16.

Usually means you have an even number of sources and they split 50/50, OR one source is wildly wrong and drags the median. Fixes:

  • Configure at least 4 sources. With 3, any one outlier creates deadlock; with 4 the intersection is robust.
  • Diversify upstream: do not use 4 servers from the same operator/ASN. See the NTP source comparison for good dual-operator options.
  • Identify the outlier with chronyc sourcestats -v — look for one source with offset > 3× the others — and treat it as a false ticker.

6. Windows w32tm equivalent

On Windows, stratum 16 manifests as the unsynchronized state of w32time or TimeState::StateNoSync.

:: Query status
> w32tm /query /status

:: Force resync from authoritative peer
> w32tm /resync /force

:: Reconfigure manual peer list
> w32tm /config /manualpeerlist:"ntp.rdem-systems.com time.cloudflare.com" /syncfromflags:manual /update
> net stop w32time && net start w32time
> w32tm /resync /force

If the resync fails, check Windows Firewall allows outbound UDP 123. On a domain-joined machine the cause is usually the Active Directory hierarchy rather than the source itself — the Windows Time troubleshooting hub decodes the PDC-emulator chain, the w32tm status fields and the Event IDs in depth.

7. VM and hypervisor gotchas

Virtualisation adds a second time authority competing with NTP. Turn it OFF inside guests that run chronyd/ntpd:

  • Hyper-V: uncheck "Time synchronization" in the Integration Services of each VM; set the Hyper-V service startup to manual via PowerShell if you want to keep it for nested VMs only.
  • VMware: open-vm-tools installs vmtoolsd which can sync the guest to the host. Disable in /etc/open-vm-tools/tools.conf with time.synchronize.tools.startup = false and related flags.
  • KVM / libvirt: avoid <clock offset="host"> with periodic sync. Use <clock offset="utc"/> and let chronyd handle it.

After disabling host-guest sync, restart chronyd and wait 1–3 poll intervals (64–256 s default) for sync to lock.

After the fix — related sites: