Helpdesk: "Patch Tuesday was Tuesday. It's Friday, and the WSUS console still says 47 updates are needing files. The Windows 11 cumulative update is approved for the Pilot group, and the pilot PCs sit at 'Downloading - 0%'. Last night's synchronization shows Failed, and the Synchronizations page doesn't say why. A forum thread says to stop WSUS, delete the WsusContent folder, run wsusutil reset, and reinstall the role if that doesn't work. Can we do that before tonight's change window?"
Not yet. "WSUS not downloading updates" is two pipelines that fail separately: synchronization brings the update metadata, and the content download brings the files. Each one has its own log lines and its own fixes. Microsoft's WSUS API documentation: "WSUS downloads the update files and required license agreements in parallel with synchronizing the update metadata." Deleting WsusContent throws away every file that did download and makes the server fetch it all again through the same broken path. Work through it as a chain: the console state and what changed → the server's view: last sync result, updates needing files, download progress → the update file settings → SoftwareDistribution.log and event 364 → the path to Microsoft Update or the upstream server: endpoint, ports, proxy, inspection → TLS 1.2 and ciphers → the content folder: space, ContentDir, permissions → BITS on the server → Windows 11 UUP MIME types and the client's download from Content → disconnected servers fed by export and import. Get-WsusServer, the WSUS administration API, SoftwareDistribution.log, Get-WinEvent, Test-NetConnection, Get-Acl, and Get-BitsTransfer are the sources for that chain. Reinstall the role behind a proxy that strips Range headers, and the new server stops at the same file.
If the files are on the server and the problem is that clients never show up, never scan, or never report, read WSUS Clients Not Reporting first. It covers client policy, the scan source, the client proxy, WsusPool, and duplicate SusClientId values, so this post doesn't repeat them. This post covers "the WSUS server won't synchronize, or it synchronizes but approved updates stay at 'needing files', downloads sit at 0, event 364 says content file download failed, or Windows 11 updates never finish, and you need a read-first path before you delete WsusContent, run wsusutil reset, or rebuild WSUS."
TL;DR
-
Sync and download are separate. A sync can succeed while files fail, and the other way round. Read
GetLastSynchronizationInfo()andGetStatus().UpdatesNeedingFilesCountbefore you pick a layer. -
The console may hide the sync error. Microsoft's known issue: "After installing KB5070881 or later updates, Windows Server Update Services (WSUS) does not display synchronization error details within its error reporting." Read
SoftwareDistribution.loginstead. - Event 364 names the reason. "Content file download failed. Reason:" is followed by an HTTP status or a BITS message, and each one points at a different layer (Step 4).
-
The endpoint is TLS 1.2 only. Microsoft:
https://sws.update.microsoft.com"accepts only Transport Layer Security (TLS) 1.2 connections." A cipher policy with no common cipher breaks sync the same way. - BITS needs Range headers. Microsoft: "If you're behind a proxy server or behind a firewall that removes this header, the file copy operation is unsuccessful." Fix the proxy or inspection rule first. Foreground BITS is the documented fallback.
-
Windows 11 needs two MIME types.
.msuand.wimat the IIS server level, from a current cumulative update or by hand. Microsoft: "Clients using Windows 11 version 22H2 might fail to install updates from WSUS if the server isn't updated."
Where in the chain did it break?
| Step | What should be true | Typical symptom when it breaks |
|---|---|---|
| 1. Symptom captured | Sync status, needing-files count, which updates, since when, what changed | "WSUS stopped downloading" with no dates |
| 2. Server's own view | Last sync Succeeded, needing-files count falling, progress moving |
Sync Failed; count stuck; bytes not moving |
| 3. Update file settings | Storage, deferred download, express, and languages match what you expect | Files never requested; clients sent to Microsoft Update |
| 4. Logs |
SoftwareDistribution.log and event 364 read for the exact reason |
Errors nobody has read |
| 5. Network path | Endpoint, ports 80/443 (or 8530/8531 upstream), proxy, inspection | Timeouts, 407, resets, downloads that stop at the same byte |
| 6. TLS | TLS 1.2 and a cipher Microsoft Update accepts | "The underlying connection was closed" |
| 7. Content folder | Free space, the right ContentDir, NETWORK SERVICE Full Control |
Disk full; access denied; content directory not accessible |
| 8. BITS | Jobs progressing; Range requests survive the path | Jobs stuck in transient error; Range header message |
| 9. UUP and client download |
.msu/.wim MIME types; clients reach Content on 8530 |
Windows 11 updates never finish; clients at 0% |
| 10. Disconnected server | Content copied, metadata imported, settings matched | Imported updates stuck in downloading |
| 11. Change | Only after Steps 1-10 agree: one layer, one change | WsusContent deleted, same failure next month |
Step 1: Capture the symptom (read-only)
Write these on the ticket first:
| Fact | Why it matters |
|---|---|
| Last sync result and time | Failed sync points at Steps 4-6; succeeded sync with stuck files points at Steps 3-9 |
| Updates needing files, now and yesterday | A falling count is a slow download; a flat count is a stuck one |
| Which updates | All of them: the path or the disk. Only Windows 11 cumulative updates: UUP, size, or inspection |
| Upstream source, proxy, firewall | Microsoft Update, an upstream WSUS server, or export/import; proxies and inspection break Range requests and TLS |
| What changed? | Firewall or inspection profile, proxy, cipher GPO, TLS hardening, a new product, a moved content folder |
Then branch on what you see:
| What you see | What it usually means (our reading unless noted) | Start at |
|---|---|---|
| Last sync Failed, error details blank | The known issue hides details in the console. Read the log | Steps 2, 4 |
SoapException: Fault occurred with fe2.update.microsoft.com in the log |
Old, decommissioned endpoint (Microsoft) | Step 5 |
| "The underlying connection was closed" | TLS version or cipher mismatch, or a proxy that ends the connection | Step 6 |
| Sync stays at 0% | Microsoft: the WSUS service "is in a stopped state" | Step 2 |
| Sync succeeds, updates needing files never moves | The content download is the broken half | Steps 3, 4, 7, 8 |
| Event 364 with a Range header message | A proxy or firewall strips HTTP 1.1 Range requests (Microsoft KB 922330) | Steps 5, 8 |
| Event 364 with HTTP 503 or 401 from an upstream WSUS server | The upstream server is overloaded or rejected the request (Q&A reports) | Step 5 |
| Only Windows 11 cumulative updates stop part-way | UUP MIME types, disk, or content inspection on the firewall | Steps 7, 9 |
| Server shows files present, clients sit at 0% | The client's download from Content, not the server's |
Step 9 |
| Disconnected server, imported updates stuck in downloading | Content not copied, or settings that don't match the export server | Step 10 |
Step 2: Read the server's own view (read-only)
Start on the WSUS server, in an elevated PowerShell session with the UpdateServices module. One object gives you the sync result, the needing-files count, and the download progress:
# Read-only. Local WSUS server (no parameters = this server)
$wsus = Get-WsusServer
# Read-only. The last synchronization: result, times, error, and per-update import errors
$sub = $wsus.GetSubscription()
$sub.GetSynchronizationStatus()
$last = $sub.GetLastSynchronizationInfo()
$last | Select-Object Result, StartTime, EndTime, Error, ErrorText
$last.UpdateErrors | Select-Object UpdateId, ErrorText -First 20
# Read-only. How many updates still lack files, and the bytes behind them
$wsus.GetStatus().UpdatesNeedingFilesCount
$wsus.GetContentDownloadProgress()
How Microsoft defines what you just read:
| Read | Microsoft's definition | How to read it (our reading unless noted) |
|---|---|---|
GetLastSynchronizationInfo().Result |
"If the synchronization process has never run, ISynchronizationInfo.Result is SynchronizationResult.NeverRun." Microsoft's sample compares it with Succeeded and Failed
|
Failed sends you to Steps 4-6 |
Error |
"If there was no error, then the value is NotApplicable." | A value here is the failure category; ErrorText carries the exception |
UpdateErrors |
Microsoft's sample checks it because the sync "could also fail with an import error" | Errors for single updates, not the whole sync |
UpdatesNeedingFilesCount |
"Number of updates on the WSUS server that do not have all the required installation files." | The console's needing-files number |
GetContentDownloadProgress() |
"The total number of bytes to download and the number of bytes downloaded so far." | Read it twice, ten minutes apart. No change means stuck |
Two traps in those reads. First, use GetStatus(), not GetUpdateStatus(), for the needing-files count. Microsoft on GetUpdateStatus: "This method updates only the UpdateCount, DeclinedUpdateCount, UpdatesWithClientErrorsCount, UpdatesNeededByComputersCount, and UpdatesUpToDateCount properties. All other properties will be 0 or empty." A Microsoft Q&A poster saw it "always 0 even when the GUI says otherwise" until switching to GetStatus(). Second, when files live on Microsoft Update, the progress number isn't about update files at all. Microsoft: "If HostBinariesOnMicrosoftUpdate is true, the return value represents the download progress of the end-user license agreements (EULAs)."
Why the console's error is blank. Microsoft lists it as a known issue on its Windows Server 2025 pages for the October 2025 WSUS security fix: "After installing KB5070881 or later updates, Windows Server Update Services (WSUS) does not display synchronization error details within its error reporting. This functionality is temporarily removed to address the Remote Code Execution Vulnerability, CVE-2025-59287." The same known issue still appears, with KB5070893, on Microsoft's August 11, 2026 Windows Server 2025 hotpatch page. We only checked Windows Server 2025 pages, and we haven't tested whether the API's ErrorText is affected. Don't roll back the security fix to get the error text back; read the log in Step 4.
A sync that never leaves 0%. Microsoft's sync troubleshooting: if a manual synchronization starts but stays at 0%, the WSUS service "is in a stopped state." Read the services:
# Read-only. WSUS service, IIS, and the WSUS app pool (service names are our note)
Get-Service -Name WsusService, W3SVC | Format-Table Name, Status, StartType
Import-Module WebAdministration
Get-WebAppPoolState -Name 'WsusPool'
If WsusPool is stopped, the clients-not-reporting post has Microsoft's 503 and private memory limit guidance.
Microsoft's health check: "run the following command on the WSUS server. Then review the Application log in Event Viewer for errors":
:: Read-only health check. Results go to the Application log
"%ProgramFiles%\Update Services\Tools\wsusutil.exe" checkhealth
| Finding | What it means (our reading unless noted) | Next |
|---|---|---|
Result is Failed, ErrorText empty or generic |
The detail is in the log | Step 4 |
Result is Succeeded, needing-files count flat for hours |
Content download is stuck | Steps 3, 4, 7, 8 |
| Count falls slowly, bytes move | It's working, just slow | Watch; BITS priority (Step 8) only if it stalls |
UpdateErrors lists a handful of updates |
Import errors for those updates, not a broken sync | Step 4: search the log for those update IDs |
Step 3: The update file settings (read-only)
Before you chase a download that isn't happening, check that the server is supposed to download anything. Microsoft: "Update files can be stored on your WSUS server or on Microsoft Update servers, depending on how you've configured your synchronization options." And: "If not, client computers will download approved updates directly from Microsoft Update."
# Read-only. Where updates come from, where files live, and what gets downloaded
$cfg = (Get-WsusServer).GetConfiguration()
$cfg | Select-Object SyncFromMicrosoftUpdate, UpstreamWsusServerName, UpstreamWsusServerPortNumber, UpstreamWsusServerUseSsl,
IsReplicaServer, HostBinariesOnMicrosoftUpdate, DownloadUpdateBinariesAsNeeded, DownloadExpressPackages,
AllUpdateLanguagesEnabled, LocalContentCachePath, UseProxy, ProxyName, ProxyServerPort, MUUrl
In the console: Options > Update Files and Languages, and Options > Update Source and Proxy Server. Microsoft's definitions:
| Property | Microsoft's definition | What it changes here (our reading unless noted) |
|---|---|---|
HostBinariesOnMicrosoftUpdate |
"Gets or sets whether updates are stored locally or whether clients download approved updates directly from Microsoft Update." |
True: nothing to download on the server; clients need internet access |
DownloadUpdateBinariesAsNeeded |
"Gets or sets whether updates are downloaded only when they are approved." |
True: unapproved updates never get files. That's normal |
DownloadExpressPackages |
"Gets or sets whether express installation packages should be downloaded." |
True: much more content per update |
SyncFromMicrosoftUpdate / UpstreamWsusServerName
|
Sync from Microsoft Update, or "the name of a local server from which to synchronize updates." | Which network path Step 5 has to test |
UseProxy / ProxyName / ProxyServerPort
|
"Gets or sets whether to use a proxy to download updates." | The proxy Step 5 tests |
Microsoft's rule for the two download properties: "To download only approved updates, set HostBinariesOnMicrosoftUpdate to false and IUpdateServerConfiguration.DownloadUpdateBinariesAsNeeded to true." And: "WSUS ignores the following property values if HostBinariesOnMicrosoftUpdate is true," which are the express and as-needed settings.
| Finding | What it means | Next |
|---|---|---|
HostBinariesOnMicrosoftUpdate is True
|
The server never stores update files. Clients that can't reach Microsoft Update sit at 0% (our reading) | Step 9, or change the storage option deliberately (Step 11) |
Update unapproved, DownloadUpdateBinariesAsNeeded True
|
Microsoft: "When you defer downloads, an update is downloaded only after it's approved." | Not a fault |
| Downstream server in a hierarchy | Microsoft: a downstream request for an update not approved upstream "forces a download on the upstream server," and the downstream server gets it "on a subsequent synchronization" | Give it one more sync before you troubleshoot |
DownloadExpressPackages True
|
Microsoft: "Express installation files are larger than the updates that are distributed to client computers because the express installation file contains all possible versions of each file that is to be updated." | Step 7: disk |
MUUrl not https://sws.update.microsoft.com on a server that syncs from Microsoft Update |
Old endpoint | Step 5 |
Microsoft: "By default, WSUS doesn't use express installation files." Turning them on to speed up a stuck download makes the download bigger (our reading).
Step 4: Read the logs: SoftwareDistribution.log and event 364 (read-only)
Microsoft points at one log for sync and import errors, on the WSUS server: %ProgramFiles%\Update Services\LogFiles\SoftwareDistribution.log. Its sync troubleshooting also shows the start lines to look for: "A manual synchronization was started." (EventId=382) and "A scheduled synchronization was started." (EventId=381). Content download failures show up there and in the Application log as event 364.
# Read-only. The last sync start, then errors after it (patterns from Microsoft's samples; the selection is ours)
$log = Join-Path $env:ProgramFiles 'Update Services\LogFiles\SoftwareDistribution.log'
Select-String -Path $log -Pattern 'EventId=38[12]' | Select-Object -Last 3
Select-String -Path $log -Pattern 'ProcessWebServiceProxyException|SoapException|WebException|EventId=364|SCHANNEL Protocol' |
Select-Object -Last 40 | ForEach-Object Line
# Read-only. Event 364 in the Application log, last 7 days (provider name from Microsoft's KB 922330 sample)
Get-WinEvent -FilterHashtable @{
LogName = 'Application'
ProviderName = 'Windows Server Update Services'
Id = 364
StartTime = (Get-Date).AddDays(-7)
} -ErrorAction SilentlyContinue | Select-Object TimeCreated, Message | Format-List
For EULA problems during sync, Microsoft's tip for the same log: "Look for .txt in the log to find relevant entries."
Map the text you find to a layer. Each row's text is quoted from the Microsoft page or Q&A thread named in it:
| Text in the log or event | Source | Points at |
|---|---|---|
SoapException: Fault occurred with an fe2.update.microsoft.com actor |
Microsoft KB 4482416: that endpoint "was fully decommissioned and is no longer reachable after July 8, 2019." | Step 5: endpoint |
| "The underlying connection was closed: An unexpected error occurred on a send." | Microsoft's sync and import article: TLS 1.0 hello, reset from the endpoint | Step 6: TLS |
| "The client and server cannot communicate, because they do not possess a common algorithm" | Same article: no protocol or cipher in common | Step 6: TLS and ciphers |
| "A connection attempt failed because the connected party didn't properly respond after a period of time, or established connection failed because connected host didn't respond." | Microsoft's Configuration Manager sync article | Step 5: firewall, proxy |
HTTP Status 407 Proxy Authentication Required or HTTP Status 502 Proxy Error
|
Same article's list of proxy and authentication errors | Step 5: proxy credentials |
| "Content file download failed. Reason: The server does not support the necessary HTTP protocol. Background Intelligent Transfer Service (BITS) requires that the server support the Range protocol header." | Microsoft KB 922330 | Steps 5, 8: Range requests |
| "Content file download failed. Reason: HTTP status 503: The service is temporarily overloaded." | A Microsoft Q&A post from a downstream server | The upstream WSUS server (Step 5) |
Event 364 with HTTP status 404
|
Microsoft Q&A threads; the answers there point at missing or corrupt content and wsusutil reset
|
Steps 7, 11 |
KB 922330's console symptom for the Range case: "A red X appears over the update." The approval-time message Q&A posters quote, "The files for this update have not yet been downloaded," only says the files aren't there yet. Event 364 says why (our reading).
Step 5: The path to Microsoft Update or the upstream server (read-only)
The endpoint. Microsoft's first check for sync or import problems is the endpoint in MUUrl (Step 3). https://sws.update.microsoft.com is the current one; https://fe2.update.microsoft.com "is decommissioned as a WSUS synchronization endpoint, and connections to it will fail." Microsoft: "Windows Server 2012 and later versions should be configured to use the https://sws.update.microsoft.com endpoint." The fix is in Step 11.
The firewall. Microsoft: "To get updates from Microsoft Update, the WSUS server uses ports 80 and 443 for the HTTP and HTTPS protocols." The topmost server needs outbound access to a list of Microsoft domains, including *.update.microsoft.com, *.windowsupdate.com, download.windowsupdate.com, download.microsoft.com, and *.delivery.mp.microsoft.com. Read the full list on Microsoft's Configure WSUS page. Microsoft is explicit about IP-based rules: "The IP addresses associated with these domains are constantly changing, so don't try to use IP address ranges instead." A downstream server only needs its upstream server: "By default, these ports are 8530 and 8531."
# Read-only. TCP reachability from the WSUS server (hosts from Microsoft's list; the selection is ours)
'sws.update.microsoft.com', 'download.windowsupdate.com' | ForEach-Object {
Test-NetConnection -ComputerName $_ -Port 443 -WarningAction SilentlyContinue |
Select-Object ComputerName, RemotePort, TcpTestSucceeded
}
Test-NetConnection -ComputerName download.windowsupdate.com -Port 80 -WarningAction SilentlyContinue |
Select-Object ComputerName, RemotePort, TcpTestSucceeded
# Read-only. A downstream server: can it reach its upstream on both ports? (WSUS-HQ is an example)
foreach ($port in 8530, 8531) {
Test-NetConnection -ComputerName WSUS-HQ.corp.contoso.com -Port $port -WarningAction SilentlyContinue |
Select-Object ComputerName, RemotePort, TcpTestSucceeded
}
Test-NetConnection "Specifies the TCP port number on the remote computer," so it proves TCP, not TLS or a full download. Behind a mandatory proxy, a failed direct test is expected (our note).
The proxy. WSUS has its own proxy setting, separate from the browser's. Microsoft: "This setting will apply only when your WSUS server runs synchronizations. By default your WSUS server will try to connect directly to the upstream server or Microsoft Update." And: "Configure WSUS with the same port number that the proxy server is configured to use." Microsoft's sync walkthrough also describes the connection layer: "After a synchronization starts, the WSUS server attempts to make an HTTP connection through WinHTTP." So read the machine's WinHTTP proxy too:
:: Read-only. The system (WinHTTP) proxy on the WSUS server
netsh winhttp show proxy
| Finding | What it means (our reading unless noted) | Next |
|---|---|---|
| Direct TCP 443 fails, no proxy configured in WSUS | Firewall blocks the server, or a proxy is required and not set | Firewall team with Microsoft's domain list, or set the proxy (Step 11) |
UseProxy True, log shows 407 |
Proxy credentials or authentication type | Step 11: the console's proxy credentials |
| Downstream server: 8530/8531 fail to the upstream | Path or upstream IIS. A 503 from upstream: Microsoft's WsusPool guidance |
The upstream server first |
| Downloads stop at the same point every time, sync works | Content inspection or AV scanning on the firewall (below) | Exclude the WSUS server from inspection (Step 11) |
Firewall content inspection. In an April 2026 Microsoft Q&A thread, a fresh WSUS on Windows Server 2022 stopped the 2026-02 and 2026-03 Windows 11 cumulative updates part-way, "with updates needing files: 1," while other updates downloaded fine. The poster's resolution: "Once I turned off content inspection for this server the update downloaded fully without issue." Microsoft's KB 922330 names one vendor case of the same kind: a SonicWALL device where the "Enable HTTP Byte-Range request with Gateway AV" setting isn't enabled. Beyond that case, treat inspection as a pattern to test (community report).
Step 6: TLS 1.2 and cipher suites (read-only)
Microsoft: https://sws.update.microsoft.com "accepts only Transport Layer Security (TLS) 1.2 connections. And some ciphers were disabled." Its Configuration Manager TLS guidance: "TLS 1.2 is supported by default for WSUS on all currently supported version of Windows Server." So on a current server, a TLS failure usually means something was changed: a cipher policy, an SCHANNEL hardening script, or .NET settings (our reading).
What WSUS logged at startup. Microsoft: "WSUS logs which SSL/TLS versions are enabled when it starts." Its sample lines after a WSUS service restart and iisreset:
SCHANNEL Protocol 'TLS 1.0' disabled
SCHANNEL Protocol 'TLS 1.1' disabled
SCHANNEL Protocols subkey for 'TLS 1.2' not found. Protocol is enabled
For Windows Server 2012 and 2012 R2 WSUS servers, Microsoft adds: "If you can't find these entries, it means the update that enables TLS 1.2 isn't installed." The Step 4 Select-String already searches for SCHANNEL Protocol.
.NET strong cryptography. Microsoft's fix for import and sync failures over TLS 1.2 starts with the .NET registry values. Read them before you set anything:
# Read-only. .NET TLS values Microsoft's TLS 1.2 guidance sets (missing = not set)
'HKLM:\SOFTWARE\Microsoft\.NETFramework\v4.0.30319',
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\.NETFramework\v4.0.30319',
'HKLM:\SOFTWARE\Microsoft\.NETFramework\v2.0.50727' | ForEach-Object {
Get-ItemProperty -Path $_ -ErrorAction SilentlyContinue | Select-Object @{ n = 'Key'; e = { $_.PSPath -replace '^.*::' } }, SchUseStrongCrypto, SystemDefaultTlsVersions
}
Microsoft: "The SchUseStrongCrypto setting allows .NET to use TLS 1.1 and TLS 1.2. The SystemDefaultTlsVersions setting allows .NET to use the OS configuration."
Cipher suites set by policy. Microsoft's Issue 5 is a GPO-configured cipher order with nothing the endpoint accepts: "If the GPO is applied, and it doesn't specify one of these ciphers, communication with WU/MU fails." Its read:
:: Read-only. Then search the report for "SSL Cipher Suite Order"
gpresult /scope computer /h GPReport.html
Microsoft's list "As of August 2020" for Windows Server 2016 and later starts with TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 and TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256; read the full list on its page, because "This list will change over time because ciphers will gradually grow weaker as technology improves." Without a GPO, the local value is Functions under HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Cryptography\Configuration\SSL\00010002.
| Finding | What it means (Microsoft unless noted) | Next |
|---|---|---|
| "An unexpected error occurred on a send" and TLS 1.0/1.1 still in use by WSUS | The endpoint resets anything below TLS 1.2 | Step 11: .NET values, restart |
| "do not possess a common algorithm" after someone disabled TLS 1.0/1.1 | WSUS import "can't use TLS 1.2" without the fix | Step 11: .NET values or w3wp.exe.config
|
| GPO sets SSL Cipher Suite Order without the endpoint's ciphers | No common cipher | The GPO owner (Step 11) |
Step 7: The content folder: space, location, and permissions (read-only)
# Read-only. Where WSUS thinks its content is, and how much room is left
$setup = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Update Services\Server\Setup'
$setup | Select-Object ContentDir, TargetDir
(Get-WsusServer).GetConfiguration().LocalContentCachePath
$drive = (Split-Path -Path $setup.ContentDir -Qualifier).TrimEnd(':')
Get-PSDrive -Name $drive | Select-Object Name, @{ n = 'FreeGB'; e = { [math]::Round($_.Free / 1GB, 1) } }, @{ n = 'UsedGB'; e = { [math]::Round($_.Used / 1GB, 1) } }
# Read-only. Who has rights on WsusContent (NETWORK SERVICE should have Full Control)
(Get-Acl -Path (Join-Path $setup.ContentDir 'WsusContent')).Access |
Select-Object IdentityReference, FileSystemRights, AccessControlType, IsInherited
# Read-only. Does IIS serve Content from the same folder? (site name varies: 'WSUS Administration' or 'Default Web Site')
Import-Module WebAdministration
Get-WebVirtualDirectory -Site 'WSUS Administration' -Name 'Content' | Select-Object Path, PhysicalPath
Microsoft's reference for the registry: under HKLM\Software\Microsoft\Update Services\Server\Setup, ContentDir is "the location under which update binaries and end user license agreement files are stored," and ContentDir\WsusContent "contains the update files." The Content virtual directory lookup at the end is our way to compare the IIS path with ContentDir. Microsoft's reference lists Content as one of the virtual roots WSUS creates, with anonymous access.
Space. Microsoft: "At a minimum, WSUS requires 20 GB to store updates locally; however, we recommend at least 40 GB." For Windows 11 UUP: "the WSUS server downloads approximately 10 GB of content per Windows version and processor architecture for each version. For example, an additional 20 GB of content is downloaded for both x64 and arm64 for Windows 11, version 22H2." Express files, all languages, and feature updates (the Upgrades classification) all add to that.
Permissions. Microsoft's server settings reference: the WSUS content directory "must have Full Control permission granted to the NT Authority\Network Service account. This permission is set by WSUS server setup when it creates the directory, but it is possible that your security software might reset this." And: "Not having this permission set will also cause BITS downloads to fail." The same page says the root folder of the drive that holds WsusContent needs Read for the Users account or NETWORK SERVICE, a permission "that WSUS setup does not configure." That page dates from the WSUS 2.0/3.0 era, so treat its details as a checklist, not a current contract (our note).
| Finding | What it means (our reading unless noted) | Next |
|---|---|---|
| Content drive nearly full | New files can't land. Microsoft warns that switching to local storage without room "may damage the WSUS installation." | Step 11: free space or movecontent
|
| NETWORK SERVICE missing or not Full Control on WsusContent | Microsoft: BITS downloads fail | Step 11: restore the permission |
ContentDir and the IIS Content path differ |
A folder moved by hand. Clients ask IIS for files WSUS stored somewhere else | Step 11: movecontent -skipcopy to realign |
| A post-install or health message: "The WSUS content directory is not accessible." with a 503 | A Microsoft Q&A report; the 503 points at IIS and WsusPool (our reading) |
The WsusPool checks in Step 2 |
Step 8: BITS on the server (read-only)
Microsoft: "WSUS uses the Background Intelligent Transfer Service (BITS) protocol for all its file transfer tasks. This includes downloads to client computers and server synchronizations." When the needing-files count is flat, look at the BITS jobs on the WSUS server:
# Read-only. All users' BITS jobs (needs admin). WSUS jobs aren't owned by your account
Get-BitsTransfer -AllUsers |
Select-Object DisplayName, JobState, OwnerAccount, BytesTransferred, BytesTotal, ErrorDescription |
Sort-Object JobState | Format-Table -AutoSize -Wrap
# Read-only. The BITS service itself
Get-Service -Name BITS | Select-Object Name, Status, StartType
-AllUsers matters. Microsoft: "By default, the cmdlet returns the jobs that are owned by the current user." The selected properties are ours. Which job names and owner WSUS uses, we haven't confirmed on a Microsoft page, so read the list rather than filter it.
Range requests and foreground mode. Microsoft's KB 922330 explains why some downloads fail behind a proxy or firewall: "When you copy a file by using BITS in background mode, the file is copied in multiple small parts. To perform this kind of copy operation, BITS uses the HTTP 1.1 Content-Range header." Then: "When BITS copies files in foreground mode, BITS doesn't use this header." Its first resolution is to fix the proxy: "Modify the proxy server settings to support HTTP 1.1 range requests. If you can't modify the proxy server in this manner, configure BITS to work in foreground mode." Microsoft's server settings reference describes the setting: "This internal setting specifies whether or not to use foreground priority for BITS downloads. The default is to use throttled downloads." Read it before you change it:
# Read-only. Current BITS priority for WSUS downloads (property form reported on Microsoft Q&A; see the note)
(Get-WsusServer).GetConfiguration().BitsDownloadPriorityForeground
KB 922330's own commands update tbConfigurationC in SUSDB with SQL for WSUS 2.0 and 3.0. Microsoft Q&A posters set the same value through the configuration object on current versions. Microsoft's property list for IUpdateServerConfiguration that we fetched doesn't show it, so treat the PowerShell form as community-documented (our note).
| Finding | What it means (our reading unless noted) | Next |
|---|---|---|
| WSUS jobs in a transient or error state with a Range message | The KB 922330 case | Fix the proxy or firewall first; foreground mode if you can't (Step 11) |
| Jobs transferring, bytes moving slowly | Throttled background mode on a busy link | Leave it, or foreground mode as a deliberate choice |
| No jobs at all, count flat | Nothing queued: settings (Step 3), disk (Step 7), or WSUS service | Steps 2, 3, 7 |
Step 9: Windows 11 UUP and the client's download (read-only)
UUP MIME types on the server. Windows 11 quality updates come as Unified Update Platform content on WSUS. Microsoft: "Install one of the following updates on the WSUS servers, or manually add the required MIME types for UUP to the WSUS server," with the 2023-02 cumulative update (or later) listed for Windows Server 2016, 2019, and 2022. The two types are .msu (application/octet-stream) and .wim (application/x-ms-wim). Microsoft: "Ensure you selected the server and not the site when adding the MIME types. The WSUS Administration site needs the MIME type entry to be inherited rather than local."
# Read-only. Server-level static content MIME map for the two UUP types (the PSPath form is ours)
Import-Module WebAdministration
Get-WebConfigurationProperty -PSPath 'MACHINE/WEBROOT/APPHOST' -Filter 'system.webServer/staticContent' -Name collection |
Where-Object fileExtension -in '.msu', '.wim' | Select-Object fileExtension, mimeType
If someone added them by hand at the wrong level, you'll see Microsoft's documented error: "Cannot add duplicate collection entry of type 'mimeMap' with unique key attribute 'fileExtension' set to '.wim'". Microsoft: "These two MIME types should only be set to local at the server level."
How clients get the files. With local storage, clients download from the WSUS server's Content virtual directory over plain HTTP. Microsoft: one port "uses TLS/HTTPS to send update metadata," and "A second port uses HTTP to send update payloads." By default that's 8530; Content is on Microsoft's list of virtual roots that shouldn't require TLS. Payloads are still protected: "When an update is downloaded, the client software verifies the payload's digital signature and hash."
When the server has every file and clients still sit at 0%, the client side has its own documented causes:
| Client finding | Microsoft's explanation | Next |
|---|---|---|
| Proxy in Internet Explorer settings only | "If a proxy was configured in Internet Explorer (User level) but not in WinHTTP (System level), connections to Windows Update will fail." |
netsh winhttp show proxy on the client |
| Proxy strips Range requests | "Windows Update uses WinHttp with Partial Range requests (RFC 7233) to download updates and applications from Windows Update servers or on-premises WSUS servers." | Allow Range requests on the proxy |
0x800706D9, stuck at 0% |
"You observe that the download for updates is stuck at 0%, especially in Windows Server 2016, where the Background Intelligent Transfer Service (BITS) service is the default Download Manager." Cause: the Windows Defender Firewall service is disabled | Enable the service. Microsoft: "Stopping the service associated with Windows Firewall with Advanced Security isn't supported by Microsoft." |
| Client never scans or reports | Not a content problem | The clients-not-reporting post |
Step 10: Disconnected (offline) WSUS servers (read-only)
Microsoft's Configure WSUS page describes the air-gapped design: one internet-connected WSUS server collects updates, they're "exported from the first server onto removable media, carried across the air gap, and imported into the second server." Export and import move metadata only. Microsoft's WSUSutil reference: "You cannot use this parameter to export update files, update approvals, or server settings." The files travel separately: Microsoft's Configuration Manager procedure copies "all files and folders" from the export server's WSUSContent folder to the disconnected server's WSUSContent folder, then runs wsusutil.exe export packagename logfile on one side and wsusutil.exe import packagename logfile on the other.
Microsoft's older disconnected-network guide adds the step that's easy to skip: "Make sure that the options for express installation files and update languages on the exporting server are compatible with the settings on the importing server."
| Finding on the disconnected server | What it means (our reading unless noted) | Next |
|---|---|---|
| Imported and approved updates stuck in downloading | The files for those updates aren't in WsusContent, or not at the paths WSUS expects. A Microsoft Q&A thread describes exactly this after import | Re-copy the whole WsusContent folder from the export server |
| Export server itself shows updates needing files | It never had the files to give | Fix the export server first (Steps 2-8), then export again |
| Express or language settings differ between the two servers | The export doesn't carry what the importing server is set to expect | Match the settings (Step 11) |
| Import fails | Microsoft: "the user that runs the WSUSUtil tool must be a member of the local Administrators group on each server." | Rerun as a local admin with a fresh package |
In that Q&A thread, the MVP answer suggests running wsusutil reset on the online server, waiting, then exporting again and copying the whole WsusContent folder (community answer).
Common false starts (read these before you change anything)
| False start | Why it hurts | Read-first alternative |
|---|---|---|
| Deleting WsusContent | Throws away every file that did download, then re-fetches all of it through the same path. Updates imported from the Microsoft Update Catalog have to be imported again (our reading, from Microsoft's cleanup note below) | Read the 364 reason first (Step 4) |
| Reinstalling the WSUS role | A new server behind the same proxy, firewall, cipher policy, and disk (our reading) | Steps 4-7 name the layer |
wsusutil reset as the first move |
It re-checks every update against the files, and the Q&A answers describe waiting about 24 hours with "no notifications of when this process is running or finished" (community). It doesn't fix a blocked path | Use it after the path is fixed, or for missing or corrupt files (Step 11) |
| Re-enabling TLS 1.0/1.1 or dropping ciphers back in | The endpoint "accepts only Transport Layer Security (TLS) 1.2 connections," so it doesn't help sync, and it weakens the server (our reading) | Step 6: the .NET values and the cipher GPO |
| Switching to "Do not store updates locally" to make the alert go away | Clients then download "directly from Microsoft Update," so every client needs internet access to the download domains | Fix the server's download (Steps 5-8) |
| Turning on express files to speed things up | Microsoft: express files need "additional bandwidth between your WSUS server, any upstream WSUS servers, and Microsoft Update, and requires additional local disk space" | Leave the default unless LAN bandwidth is the problem |
| Running the cleanup wizard during triage | Microsoft: "all the private update files that you've downloaded from the Microsoft Update Catalog site are also removed." | Run cleanup as maintenance, after the download works |
| Adding the UUP MIME types at the site level | Microsoft: the WSUS Administration site "needs the MIME type entry to be inherited rather than local." Duplicate entries break later updates | Server level only, or install the cumulative update |
Step 11: Change one layer, then prove it (only after the read)
Pick the one change Steps 1-10 point at. Save the current configuration first, so you can compare or put it back:
# Low-risk write. Save the WSUS configuration and setup key before any change (our habit)
New-Item -Path C:\Temp -ItemType Directory -Force | Out-Null
(Get-WsusServer).GetConfiguration() | Export-Clixml -Path C:\Temp\wsus-config-before.xml
reg export 'HKLM\SOFTWARE\Microsoft\Update Services\Server\Setup' C:\Temp\wsus-setup-before.reg /y
The endpoint (Step 5). Microsoft's script from KB 4482416, for WSUS on Windows Server 2012 and later. Microsoft: "Don't run the scripts on a WSUS server that's not the topmost server." The read lines come first in Microsoft's own version:
# Change, on the topmost WSUS server only. Microsoft's KB 4482416 script; close all WSUS consoles first
$server = Get-WsusServer
$config = $server.GetConfiguration()
# Check current settings before you change them
$config.MUUrl
$config.RedirectorChangeNumber
# Update the settings if MUUrl is https://fe2.update.microsoft.com/v6
$config.MUUrl = "https://sws.update.microsoft.com"
$config.RedirectorChangeNumber = 4002
$config.Save()
iisreset
Restart-Service *Wsus* -v
The upstream source (Step 3). Set-WsusServerSynchronization supports -WhatIf:
# Change. Dry-run first (WSUS-HQ is an example upstream; or use -SyncFromMU for Microsoft Update)
Set-WsusServerSynchronization -UssServerName 'WSUS-HQ.corp.contoso.com' -PortNumber 8531 -UseSsl -WhatIf
The proxy and firewall (Step 5). Set the proxy under Options > Update Source and Proxy Server > Proxy Server, with credentials if it needs them. For Range requests or content inspection, ask for an exception scoped to the WSUS server before you touch BITS, and test with one large update (our view).
TLS (Step 6). Microsoft's Resolution for issue 1: "Configure .NET Framework to use TLS 1.2 by using registry keys," then "Restart the server after you set the registry keys." The values, from Microsoft's TLS 1.2 guidance (repeat for WOW6432Node and v2.0.50727 as listed there):
# Change. Microsoft's .NET strong-crypto values, 64-bit v4 key shown. Dry-run first, then restart the server
$key = 'HKLM:\SOFTWARE\Microsoft\.NETFramework\v4.0.30319'
Set-ItemProperty -Path $key -Name SchUseStrongCrypto -Value 1 -Type DWord -WhatIf
Set-ItemProperty -Path $key -Name SystemDefaultTlsVersions -Value 1 -Type DWord -WhatIf
For a cipher GPO, change the policy at its source to include one of Microsoft's listed ciphers; don't edit the local key under a GPO that will rewrite it (our reading).
BITS foreground mode (Step 8). Only after the proxy owner says Range requests can't be allowed. Our form, through the configuration object (community-documented, see Step 8), then Microsoft's documented restart of the Update Services service:
# Change. Foreground BITS for WSUS downloads. Read first, set, save, then restart WSUS (dry-run the restart)
$cfg = (Get-WsusServer).GetConfiguration()
$cfg.BitsDownloadPriorityForeground
$cfg.BitsDownloadPriorityForeground = $true
$cfg.Save()
Restart-Service -Name WsusService -WhatIf
Disk and location (Step 7). Free space first: decline what you don't need, then cleanup as maintenance. To move content, Microsoft's syntax is wsusutil.exe movecontent contentpath logfile [-skipcopy]; -skipcopy "enables you to change the location of local WSUS update storage without copying any files" (Microsoft's archived WSUS blog). Create the new folder first:
:: Change. Move content to E:\WSUS and log it (paths are examples). Run from %ProgramFiles%\Update Services\Tools
wsusutil.exe movecontent E:\WSUS E:\WSUS-move.log
Use -skipcopy only when the files are already at the new path (our reading).
Permissions (Step 7). Save the current ACL, then restore NETWORK SERVICE Full Control on WsusContent. (OI)(CI) makes it inherit to files and subfolders; F is full access:
# Low-risk write: save the ACL first. Then the change (D:\WSUS is an example ContentDir)
icacls 'D:\WSUS\WsusContent' /save C:\Temp\wsuscontent-acl.txt /t
icacls 'D:\WSUS\WsusContent' /grant 'NT AUTHORITY\NETWORK SERVICE:(OI)(CI)F'
UUP MIME types (Step 9). Install the current cumulative update on the WSUS server first. If you can't, add both types at the IIS server node; Microsoft's Windows IT Pro blog has the appcmd form:
# Change, server level. From Microsoft's Windows IT Pro blog; only if the read in Step 9 found them missing
& $Env:WinDir\system32\inetsrv\appcmd.exe set config /section:staticContent /+"[fileExtension='.msu',mimeType='application/octet-stream']"
& $Env:WinDir\system32\inetsrv\appcmd.exe set config /section:staticContent /+"[fileExtension='.wim',mimeType='application/x-ms-wim']"
Missing or corrupt files (Steps 4, 7). Once the path, disk, and permissions are right, Microsoft's tool for the content itself:
:: Change. Re-verifies content against the database and re-downloads what's missing or corrupt
"%ProgramFiles%\Update Services\Tools\wsusutil.exe" reset
Microsoft: "If update files are missing or have been corrupted, WSUS downloads the update files again." The API equivalent is ResetAndVerifyContentState(), which verifies "that all update files on the WSUS server are valid." Run one or the other once, then wait. For a disconnected server, match settings, re-copy WsusContent, and import a fresh package (Step 10).
Then prove it. Run one manual sync, then read the same values as Step 2:
# Read-only. Sync result, the needing-files count, bytes, and any new 364s since the change
$wsus = Get-WsusServer
$wsus.GetSubscription().GetLastSynchronizationInfo() | Select-Object Result, StartTime, EndTime, Error
$wsus.GetStatus().UpdatesNeedingFilesCount
$wsus.GetContentDownloadProgress()
Get-WinEvent -FilterHashtable @{ LogName = 'Application'; ProviderName = 'Windows Server Update Services'; Id = 364; StartTime = (Get-Date).AddHours(-2) } -ErrorAction SilentlyContinue |
Select-Object TimeCreated, Message
Read the count again an hour later and the next morning; it should fall. Then check one pilot client: its download should move past 0%.
When a change is justified
| Finding | Prefer | Avoid |
|---|---|---|
Old MUUrl endpoint |
Microsoft's KB 4482416 script on the topmost server | Running it on downstream servers |
| TLS or cipher mismatch | .NET strong-crypto values; fix the cipher GPO at its source | Re-enabling TLS 1.0/1.1 |
| Range headers stripped | A proxy or firewall exception for the WSUS server | Foreground BITS as the first move |
| Content inspection breaks large files | An inspection exception scoped to the WSUS server | Turning inspection off for the whole network |
| Disk full | Decline unneeded updates, cleanup, or movecontent to a bigger drive |
Deleting WsusContent |
| Windows 11 UUP files missing | Current cumulative update on the WSUS server, or MIME types at server level | MIME types on the WSUS Administration site |
| Files missing after a restore or a fixed path |
wsusutil reset once, then wait |
Reset, delete, reinstall in the same afternoon |
FAQ
Why is WSUS not downloading updates?
Either synchronization is failing (no new metadata) or the content download is failing (metadata, no files). Read the last sync result and GetStatus().UpdatesNeedingFilesCount first. Then read SoftwareDistribution.log and event 364 for the exact reason: an old endpoint, TLS or ciphers, a proxy or firewall, a full or locked-down content folder, or BITS Range requests.
What does "updates needing files" mean in WSUS?
Updates that are approved, or set to download, whose files aren't all on the server yet. Microsoft defines the count as updates "that do not have all the required installation files." With deferred downloads on, unapproved updates don't count against you, because they're only downloaded "after it's approved."
How do I fix WSUS sync failed "The underlying connection was closed"?
It's usually TLS. Microsoft's sync endpoint accepts only TLS 1.2, and some ciphers were removed. Set the .NET SchUseStrongCrypto and SystemDefaultTlsVersions values, check for a cipher suite GPO, restart, and sync again. On a server that syncs through a proxy, check that the proxy isn't ending the connection.
Does wsusutil reset delete updates?
No. Microsoft: it verifies "that every update metadata row in the WSUS database corresponds to update files stored in the local update file storage location," and re-downloads files that are missing or corrupt. It can take a long time and doesn't fix a blocked network path, so fix the path first.
Why won't WSUS download Windows 11 updates?
Check the UUP requirements first: the .msu and .wim MIME types at the IIS server level (or a current cumulative update on the WSUS server) and enough disk for about 10 GB per Windows version and architecture. If downloads stop part-way at the same point, check firewall content inspection, which a 2026 Microsoft Q&A thread identified for Windows 11 cumulative updates.
Related posts
-
WSUS Clients Not Reporting (the client half: policy, scan source, client proxy, IIS and
WsusPool, and duplicateSusClientIdvalues) - Windows Update Rings for Intune Pilots (if WSUS's deprecation has you planning cloud-managed updates for some devices)
- Intune Feature Updates: Ring Deferral vs a Feature Updates Policy vs Windows Autopatch (which cloud tool owns feature updates once WSUS doesn't)
Free checklist
A WSUS server that looked healthy until a firewall inspection profile changed is a change nobody tested from where the files flow. So is a Conditional Access policy enforced before anyone read the report-only results. The free Conditional Access pre-enforcement checklist keeps break-glass accounts, pilot groups, and report-only review on one page:
If you want the rest of the Intune runway written down for the team (enrollment hygiene, compliance phasing, break/fix cards and read-only PowerShell snapshots), the Intune & M365 Admin Starter Pack pairs with this triage: https://cashflow4375.gumroad.com/l/joonf?utm_source=devto&utm_medium=article&utm_campaign=aps_first_sale&utm_content=wsus-not-downloading-updates
Admin Pack Studio; not affiliated with Microsoft. Steps 1-10 favor read-only checks: Get-WsusServer, GetSubscription() / GetLastSynchronizationInfo() / GetSynchronizationStatus(), GetStatus(), GetContentDownloadProgress(), GetConfiguration(), Get-Service, Get-WebAppPoolState, wsusutil checkhealth, Select-String on SoftwareDistribution.log, Get-WinEvent, Test-NetConnection, netsh winhttp show proxy, Get-ItemProperty, gpresult, Get-PSDrive, Get-Acl, Get-WebVirtualDirectory, Get-BitsTransfer -AllUsers, and Get-WebConfigurationProperty. Export-Clixml, reg export, and icacls /save write local files. The endpoint script, Set-WsusServerSynchronization, proxy settings, firewall exceptions, the .NET TLS values, cipher policy changes, BitsDownloadPriorityForeground, wsusutil movecontent, icacls /grant, MIME type changes, wsusutil reset, ResetAndVerifyContentState(), export/import, and service restarts are deliberate changes. Change one layer at a time, test with one update first, and check current Microsoft Learn for version-specific behavior.
Top comments (0)