85°F Knoxville
Mon–Fri 9–5 ETAnswered by a human
Automation · RESOLVED

Fixing Windows Time Sync: Clock Wrong, Can't Log In

Law firm paralegal locked out Monday morning. Clock showing March 2019. Kerberos won't authenticate with 5+ minute time drift.

under 15 minutes
Time to resolution

Incident

Monday morning, law firm. Paralegal back from a two-week vacation tries to log in and gets "The trust relationship between this workstation and the primary domain has failed." Their internal IT had already tried rejoining the domain (failed), resetting her AD computer account (no change), and resetting her password (also no change). By the time it landed with us, she'd been locked out most of the morning.

The clock in the bottom-right corner of Windows read March 14, 2019, 08:47 AM. Actual date was September 2, 2025. That's the whole story — everything after this is just untangling what six years of time drift does to a domain-joined machine.

What we found

  • system clock: March 14, 2019 08:47 AM
  • actual date: September 2, 2025
  • time drift: 6+ years (2,363 days)
  • Kerberos tolerance: 5 minutes, per default domain policy
  • root cause: dead CMOS battery on a 7-year-old laptop

The laptop had been powered off and unplugged the entire vacation. With a dead CMOS battery, every power loss resets the RTC to its BIOS default — which, on this particular Lenovo, is March 2019. Plug in, boot up, and Windows sees itself as six years in the past. Kerberos will not authenticate outside a 5-minute window. Six years is outside that window.

Initial diagnostics

Our RMM agent still worked — it doesn't rely on domain auth, so the broken time didn't break our channel into the box. First thing we checked was the time service:

w32tm /query /status

  • Leap Indicator: 3 (not synchronized)
  • Stratum: 0 (unspecified)
  • Last Successful Sync Time: unspecified
  • Source: Free-running System Clock
  • Poll Interval: 10 (1024s)

"Free-running System Clock" and "Last Successful Sync Time: unspecified" are the flags. The Windows Time service had never successfully synced since boot. It was trying to pull time from the DC, but it couldn't Kerberos-authenticate to make the request, because... the time was wrong. Classic chicken-and-egg.

Why their attempts failed

Every standard fix assumes the domain trust is the problem. None of them work when the real problem is time:

  • rejoin domain: "network path not found" — the machine can't even authenticate to find the DC
  • reset AD computer account: no effect, the machine still can't present a valid ticket
  • w32tm /resync: "the computer did not resync because no time data was available"
  • restart W32Time: service comes back up but can't sync from a source it can't authenticate to

Domain-joined machines sync time from the DC. To talk to the DC you need a Kerberos ticket. To get a ticket, time has to be within 5 minutes. If your clock is off by six years, you are completely locked out of the domain and out of every domain-mediated fix for the domain lockout.

Resolution

Break the loop by taking the DC out of the time-sync picture entirely. Point the machine at external NTP, force the sync, and let everything else catch up once the clock is right. We deployed this script via RMM:

time_sync_fix.ps1View on GitHub →
$ErrorActionPreference = 'Stop'

<#
██╗     ██╗███╗   ███╗███████╗██╗  ██╗ █████╗ ██╗    ██╗██╗  ██╗
██║     ██║████╗ ████║██╔════╝██║  ██║██╔══██╗██║    ██║██║ ██╔╝
██║     ██║██╔████╔██║█████╗  ███████║███████║██║ █╗ ██║█████╔╝
██║     ██║██║╚██╔╝██║██╔══╝  ██╔══██║██╔══██║██║███╗██║██╔═██╗
███████╗██║██║ ╚═╝ ██║███████╗██║  ██║██║  ██║╚███╔███╔╝██║  ██╗
╚══════╝╚═╝╚═╝     ╚═╝╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝ ╚══╝╚══╝ ╚═╝  ╚═╝
================================================================================
 SCRIPT   : Time Sync Fix                                                v1.0.3
 AUTHOR   : Limehawk.io
 DATE     : January 2026
 USAGE    : .\time_sync_fix.ps1
================================================================================
 FILE     : time_sync_fix.ps1
DESCRIPTION : Fixes Windows time synchronization by resetting NTP configuration
--------------------------------------------------------------------------------
 README
--------------------------------------------------------------------------------
 PURPOSE

 Fixes Windows time synchronization by setting the timezone, resetting the
 Windows Time service, configuring NTP servers, and forcing a time sync.
 Resolves common time drift and synchronization issues.

 DATA SOURCES & PRIORITY

 1) Hardcoded values (defined within the script body)
 2) Windows Time service (w32time)

 REQUIRED INPUTS

 - TimeZone   : Windows timezone ID (e.g., "Eastern Standard Time")
 - NtpServers : Comma-separated list of NTP servers

 SETTINGS

 - Uses pool.ntp.org servers by default
 - Sets SpecialPollInterval to 86400 seconds (24 hours)
 - Configures w32time triggers for network on/off

 BEHAVIOR

 1. Sets the system timezone
 2. Stops the Windows Time service
 3. Unregisters and re-registers w32time
 4. Configures NTP poll interval in registry
 5. Sets service triggers for network connectivity
 6. Starts the Windows Time service
 7. Configures NTP server list
 8. Forces immediate time resync

 PREREQUISITES

 - Windows 10/11
 - Admin privileges required
 - Network connectivity to NTP servers

 SECURITY NOTES

 - No secrets in logs
 - Modifies system time settings
 - Uses public NTP servers

 EXIT CODES

 - 0: Success
 - 1: Failure

 EXAMPLE RUN

 [INFO] INPUT VALIDATION
 ==============================================================
 Time Zone   : Eastern Standard Time
 NTP Servers : 0.pool.ntp.org,1.pool.ntp.org,2.pool.ntp.org,3.pool.ntp.org

 [RUN] OPERATION
 ==============================================================
 Setting timezone...
 Stopping Windows Time service...
 Re-registering Windows Time service...
 Configuring NTP poll interval...
 Setting service triggers...
 Starting Windows Time service...
 Configuring NTP servers...
 Forcing time resync...

 [OK] RESULT
 ==============================================================
 Status    : Success
 Time Zone : Eastern Standard Time
 Time      : 2025-11-29 14:32:15

 [OK] SCRIPT COMPLETED
 ==============================================================
--------------------------------------------------------------------------------
 CHANGELOG
--------------------------------------------------------------------------------
 2026-01-19 v1.0.3 Fixed EXAMPLE RUN section formatting
 2026-01-19 v1.0.2 Updated to two-line ASCII console output style
 2025-12-23 v1.0.1 Updated to Limehawk Script Framework
 2025-11-29 v1.0.0 Initial Style A implementation
================================================================================
#>

Set-StrictMode -Version Latest

# ==== STATE ====
$errorOccurred = $false
$errorText = ""

# ==== HARDCODED INPUTS ====
$TimeZone = "Eastern Standard Time"
$NtpServers = "0.pool.ntp.org,1.pool.ntp.org,2.pool.ntp.org,3.pool.ntp.org"

# ==== VALIDATION ====
if ([string]::IsNullOrWhiteSpace($TimeZone)) {
    $errorOccurred = $true
    if ($errorText.Length -gt 0) { $errorText += "`n" }
    $errorText += "- TimeZone is required."
}
if ([string]::IsNullOrWhiteSpace($NtpServers)) {
    $errorOccurred = $true
    if ($errorText.Length -gt 0) { $errorText += "`n" }
    $errorText += "- NtpServers is required."
}

if ($errorOccurred) {
    Write-Host ""
    Write-Host "[ERROR] VALIDATION FAILED"
    Write-Host "=============================================================="
    Write-Host $errorText
    exit 1
}

# ==== RUNTIME OUTPUT ====
Write-Host ""
Write-Host "[INFO] INPUT VALIDATION"
Write-Host "=============================================================="
Write-Host "Time Zone   : $TimeZone"
Write-Host "NTP Servers : $NtpServers"

Write-Host ""
Write-Host "[RUN] OPERATION"
Write-Host "=============================================================="

try {
    # Set timezone
    Write-Host "[RUN] Setting timezone..."
    tzutil /s "$TimeZone"
    if ($LASTEXITCODE -ne 0) {
        throw "Failed to set timezone. Verify timezone ID is valid."
    }

    # Stop Windows Time service
    Write-Host "[RUN] Stopping Windows Time service..."
    Stop-Service -Name w32time -Force -ErrorAction SilentlyContinue
    Start-Sleep -Seconds 2

    # Unregister and re-register the service
    Write-Host "[RUN] Re-registering Windows Time service..."
    w32tm /unregister 2>$null
    Start-Sleep -Seconds 1
    w32tm /register 2>$null
    Start-Sleep -Seconds 1

    # Configure SpecialPollInterval (24 hours = 86400 seconds)
    Write-Host "[RUN] Configuring NTP poll interval..."
    $regPath = "HKLM:\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpClient"
    Set-ItemProperty -Path $regPath -Name "SpecialPollInterval" -Value 86400 -Type DWord -Force

    # Set service triggers
    Write-Host "[RUN] Setting service triggers..."
    sc.exe triggerinfo w32time start/networkon stop/networkoff 2>$null

    # Start Windows Time service
    Write-Host "[RUN] Starting Windows Time service..."
    Start-Service -Name w32time -ErrorAction Stop
    Start-Sleep -Seconds 2

    # Configure NTP servers
    Write-Host "[RUN] Configuring NTP servers..."
    $peerList = ($NtpServers -split ',') | ForEach-Object { "$_,0x1" }
    $peerListString = $peerList -join ' '
    w32tm /config /manualpeerlist:"$peerListString" /syncfromflags:manual /update
    if ($LASTEXITCODE -ne 0) {
        Write-Host "[WARN] NTP configuration returned non-zero exit code"
    }

    # Force resync
    Write-Host "[RUN] Forcing time resync..."
    Start-Sleep -Seconds 2
    w32tm /resync /force
    if ($LASTEXITCODE -ne 0) {
        Write-Host "[WARN] Time resync returned non-zero exit code"
    }

} catch {
    $errorOccurred = $true
    $errorText = $_.Exception.Message
}

if ($errorOccurred) {
    Write-Host ""
    Write-Host "[ERROR] ERROR OCCURRED"
    Write-Host "=============================================================="
    Write-Host $errorText
}

# Get current time info
$currentTime = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$currentTz = (Get-TimeZone).Id

Write-Host ""
Write-Host "[INFO] RESULT"
Write-Host "=============================================================="
if ($errorOccurred) {
    Write-Host "[ERROR] Status : Failure"
} else {
    Write-Host "[OK] Status    : Success"
    Write-Host "Time Zone : $currentTz"
    Write-Host "Time      : $currentTime"
}

Write-Host ""
Write-Host "[INFO] FINAL STATUS"
Write-Host "=============================================================="
if ($errorOccurred) {
    Write-Host "[ERROR] Time synchronization fix failed. See error above."
} else {
    Write-Host "[OK] Time synchronization has been reset and configured."
}

Write-Host ""
Write-Host "[INFO] SCRIPT COMPLETED"
Write-Host "=============================================================="

if ($errorOccurred) {
    exit 1
} else {
    exit 0
}

Why this works

  • NTP servers don't require authentication — pool.ntp.org will tell anyone what time it is
  • that bypasses Kerberos, which bypasses the chicken-and-egg entirely
  • unregister/register w32time clears any corrupted service state from years of failed sync attempts
  • service triggers (start/networkon) make sure the laptop re-syncs whenever it gets a network, which is the pattern you want on a mobile device
  • /force ignores the rate limiter — when you're six years off, that's not your concern

Outcome

Script ran, time synced from pool.ntp.org in about 3 seconds. Clock jumped from March 2019 to September 2025. She logged in on the next try with her normal credentials — cached creds worked because the trust relationship was never actually broken, the machine just couldn't authenticate to prove it.

  • time to resolution: under 15 minutes from escalation
  • time correction: 6 years, 171 days
  • domain rejoin: not required
  • user productivity lost: about 2 hours

Follow-up actions:

  • ordered CMOS battery replacement (CR2032, ~$3)
  • added the laptop to the hardware refresh list — it's 7 years old, this isn't the last thing going wrong
  • added the script to our onboarding checklist for machines coming out of storage, since they tend to hit the same failure

Key takeaways