An update installs cleanly. The device reports no restart required. Three weeks later your vulnerability scanner is still flagging the CVE that patch was supposed to close.
Or the mirror image: a laptop has reported restart pending for eleven days, has been rebooted six times, and every new cumulative update on it fails.
Both are the same defect, and it is almost never in Windows. It is in the thing doing the checking. "Pending reboot" is not a flag. It is a minimum of five independent markers, each owned by a different component, written at different times and cleared by different code. Most RMM and compliance tools check one.
The short version
- There is no single reboot-pending bit. Microsoft's own
Microsoft.Windows/RebootPendingresource documents five causes: Windows Update, Component-Based Servicing, pending file renames, pending computer rename, pending domain join. - CBS
RebootPendingandPackagesPendingare registry subkeys. A check written withGet-ItemPropertyinstead ofTest-Pathreturns "no reboot needed" forever. PendingFileRenameOperationsis the opposite: a realREG_MULTI_SZvalue under Session Manager.- A CBS flag that survives a reboot means
%windir%\WinSxS\pending.xmlstill holds unapplied operations. Until that drains, the servicing stack will not open a new session and your next cumulative update fails. - Diagnose every marker read-only before deleting any of them. Deleting the CBS key while
pending.xmlexists regenerates the key on the next boot and destroys the evidence naming the stuck package.
What is covered
The problem: one flag checked, five that matter
This failure has two shapes that look like opposites. They are the same blind spot seen from two sides.
The false negative. Your report says the KB is installed, Get-HotFix agrees, the device says no restart required. But the binaries on disk are still the old ones, because the replacement was deferred to boot and that boot never drained the queue. The patch is registered, not in effect.
The false positive. A device reports reboot-pending permanently. Users reboot; it comes back. Every subsequent update fails, because Windows Update genuinely refuses to install while a mandatory restart is outstanding. That refusal is documented behaviour, not a bug.
Here is the check that ships inside a startling number of monitoring scripts.
Read that first command again. It asks for the values inside a container that has no values in it. RebootPending is a key: it exists or it does not, and its existence is the signal. Microsoft's own reference script enumerates subkey names with GetSubKeyNames() and tests for the string RebootPending among them, precisely because there is no value to read.
So the tool returns $null, the rule evaluates to compliant, and the device sails through reporting with fourteen queued file replacements and a blocked servicing stack.
wuauserv and rename SoftwareDistribution. Do neither yet. Both destroy the evidence identifying the stuck package, and neither addresses pending.xml, which is what actually regenerates the flag. You get the same device back tomorrow with no trail to follow.Why it happens: five owners, one label
There is no single flag because no single component owns "restart". Servicing, Windows Update, the file system, the computer identity and your management agent each have their own reason to want one, and each records it their own way.
Microsoft enumerates this directly. The Microsoft.Windows/RebootPending resource states a reboot may be required due to Windows Updates, Component-Based Servicing, pending file rename operations, pending computer rename, or pending domain join. Five causes, one boolean. That resource is explicitly a proof-of-concept, but its list is the clearest official statement that the answer is a union of independent checks.
The five authoritative sources
| Source | Owning component | Location |
|---|---|---|
| CBS reboot pending | CBS, via the TrustedInstaller service | HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing (subkeys) |
| Windows Update reboot required | Windows Update Agent | HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired (subkey) |
| Pending file renames | Session Manager, via MoveFileEx callers | HKLM\SYSTEM\CurrentControlSet\Control\Session Manager, value PendingFileRenameOperations |
| Pending computer rename | Computer name configuration | ...\Control\ComputerName\ActiveComputerName vs ...\ComputerName\ComputerName |
| ConfigMgr client reboot state | ConfigMgr client agent | WMI: root\ccm\ClientSDK, class CCM_ClientUtilities |
A sixth exists where it applies: a pending domain join, recorded by Netlogon under HKLM\SYSTEM\CurrentControlSet\Services\Netlogon. Microsoft's documentation for JoinDomainOrWorkgroup is explicit that the computer must be restarted afterwards.
Inside the CBS parent key
Component-Based Servicing is where most real patching pain lives. Everything below hangs off one parent.
Shared parent key for the table below. All three are subkeys, tested with Test-Path.
| Value or subkey | Meaning | What to look for |
|---|---|---|
RebootPending | Staged work that can only complete during boot, because a component could not be replaced in place. | Present at all. Still present after a successful restart means a stuck queue, not a stale flag. |
PackagesPending | Package records awaiting completion. Tells you which KB is stuck. | Enumerate its child keys. Names map to KB numbers: your root cause, not a nuisance to delete. |
RebootInProgress | A servicing reboot was initiated and never concluded. | Appears with RebootPending after an interruption, such as a hard power-off during "Working on updates". |
RebootPending, CBS PackagesPending and Auto Update\RebootRequired are keys needing Test-Path. PendingFileRenameOperations is a value needing Get-ItemProperty. Use the wrong one and you get a confident, permanent, wrong answer.Why a stuck CBS flag blocks the next update
This is what turns a cosmetic reporting problem into a patching outage, and it dictates the fix.
When CBS installs a component and a target file is in use, it cannot swap it there and then. It writes the outstanding primitive and advanced installer operations into a transaction file at %windir%\WinSxS\pending.xml, to be applied on the following boot before the files are referenced.
That transaction is why the flag exists. RebootPending is not a reminder to the user; it is the stack recording that it holds an open, incomplete transaction. A servicing stack with an open transaction will not begin a new one, because that would interleave two sets of component changes over the same store.
So the loop is: the queue does not drain, because a file is still locked, store permissions are wrong, or the transaction is damaged. The flag is rewritten. The next cumulative update requests a session, is refused, and fails. Delete the flag by hand and it returns on the next boot, because pending.xml is still there and the stack re-derives its state from the transaction, not from the flag.
Windows Update surfaces the refusal with a documented code. WU_E_INSTALL_NOT_ALLOWED, 0x80240016, is defined in Wuerror.h as an operation that "tried to install while another installation was in progress or the system was pending a mandatory restart." Its benign sibling WU_S_REBOOT_REQUIRED, 0x00240005, means the system must be restarted to complete installation. Repeated 0x80240016 on one device points at a stuck transaction rather than content or connectivity.
The binaries involved
| Binary | Role | Location |
|---|---|---|
TrustedInstaller.exe | Windows Modules Installer service. Owns the component store and writes the CBS markers. Legitimately Stopped when idle. | %windir%\servicing |
cbscore.dll | Servicing stack core, loaded by TrustedInstaller. Implements session handling, so this is the code that refuses a new session while a transaction is open. | %windir%\System32 |
TiWorker.exe | Windows Modules Installer Worker. Does the component work; the process burning CPU during servicing. | %windir%\WinSxS |
poqexec.exe | Primitive operations queue executor. Applies the deferred operations at boot. | %windir%\System32 |
wuaueng.dll | Windows Update Agent engine. Owns the Auto Update\RebootRequired marker. Lab device: 1509.2607.1012.0. | %windir%\System32 |
TrustedInstaller and the operations it performs write to %windir%\Logs\CBS\CBS.log, where you go once the registry has told you which marker fired.
TrustedInstaller showing as Stopped is not a fault, and is the most common false alarm here. On the clean Windows 11 lab device, the healthy idle baseline was wuauserv=Running/Manual, bits=Running/Automatic, cryptsvc=Running/Automatic, UsoSvc and DoSvc=Running/Automatic, and trustedinstaller=Stopped/Manual. It is demand-start. Do not "fix" it.How to verify: a read-only sweep of every source
Work through this in order. Every step is read-only. You are identifying which marker fired, because that determines the fix, and a wrong guess turns a five-minute job into a reimage.
- Establish whether a restart actually happened. Check the System log for User32 Event 1074, which records a planned restart with the requesting process and a reason code. If the device genuinely never restarted, you have a compliance problem, not a servicing one.
- Sweep all markers at once with the script below. Never check them one at a time; the point is seeing which ones disagree.
- Only
Auto Update\RebootRequiredset, CBS clean: an ordinary Windows Update restart still owed. Benign. - Only
PendingFileRenameOperationspopulated: read its contents first. This is usually a third-party installer or AV update, not Windows servicing, and clears on the next boot. - CBS
RebootPendingset: check whether%windir%\WinSxS\pending.xmlexists and enumeratePackagesPending. This is the branch that blocks future updates, and those two artefacts name the stuck package. - CBS
RebootPendingpersisted through a confirmed restart (an Event 1074 after the flag was set): a stuck transaction. Go to CBS.log and search for the package named inPackagesPending. - Markers clean but ConfigMgr still reports pending: the client's state is stale and the fix belongs on the agent, not in the registry.
The script below checks every source in one pass and reports which fired. It reads only; there is no remediation in it by design.
Two design choices matter. The CBS and Auto Update checks use Test-Path because their markers are keys; Session Manager uses Get-ItemProperty because its marker is a value. Mixing those up is the original sin of every broken reboot report.
The ConfigMgr branch is guarded because root\ccm\ClientSDK does not exist on an Intune-only device, where an unguarded call throws.
Here is the output from a device in the bad state, where the flag outlived a restart.
CBS set with Windows Update clear is the signature of the blocked-servicing case, and exactly what a single-source check misses most often, because many tools check the WindowsUpdate\Auto Update location rather than the CBS one.
Now name the stuck package, still read-only.
That format is frequently misread as a list of single files. It is a sequence of null-terminated pairs: source then destination is a rename on boot, source then an empty entry is a delete on boot. Session Manager processes them in issue order, and entries come from any process calling MoveFileEx with the delay-until-reboot flag.
Above, that is a vendor agent replacing its own DLL, not Windows servicing: clearing the CBS key would do nothing for it.
Event ID catalog
All of the below is one channel: Microsoft-Windows-WindowsUpdateClient/Operational (Event Viewer: Applications and Services Logs, Microsoft, Windows, WindowsUpdateClient, Operational).
| Event ID | Message | What it tells you |
|---|---|---|
| 26 | Windows Update successfully found N updates | Detection works and the agent reaches its source. Confirmed on the lab device. |
| 44 | Windows Update started downloading an update | Transfer began. No later 41 points at BITS or delivery, not a reboot problem. |
| 41 | An update was downloaded | Content is on disk. Confirmed on the lab device. Failures past here are servicing, not networking. |
| 43 | Installation Started: Windows has started installing the following update | The agent handed off to the servicing stack. A 43 with no matching 19 is where stuck transactions live. |
| 19 | Installation Successful: Windows successfully installed the following update | The agent's view of success. It can be logged while the change is only staged, so a 19 is not proof the patch is in effect. |
That last row is the false negative in one line. Event 19 plus a CBS RebootPending that never clears is a device your inventory calls patched and your scanner calls vulnerable.
The fix: match the remedy to the marker that fired
There is no single fix, because there was no single cause. Take the branch your diagnostic landed on.
Only Auto Update\RebootRequired. Restart the device. That is the whole fix. Do not touch the registry; this marker is the agent doing its job correctly.
Only PendingFileRenameOperations. Read the pairs, identify the owning product, restart. If it repopulates every boot with the same pairs, the fault is that vendor's installer. Do not delete the value: you would be cancelling a file replacement some product depends on, occasionally half of an update.
A computer rename is pending. Restart. To cancel it instead, set the value under the ComputerName key back to the currently active name so the two agree. Correct the configuration, do not delete the key.
CBS RebootPending set, no restart yet since servicing. Restart properly and re-run the diagnostic. A single clean boot resolves most of these, and everything below is then unnecessary.
CBS RebootPending survived a confirmed restart. This is the real case, and order of operations matters:
- Capture evidence first. Save the
PackagesPendingsubkey names, copy%windir%\Logs\CBS\CBS.logaside, note whetherpending.xmlexists. If this escalates to Microsoft, that is the package they will ask for. - Install the latest Servicing Stack Update. The stack repairs itself more often than people expect, an SSU is the documented first move for TiWorker and CBS failures, and it is the least invasive item here.
- Let the transaction complete on its own terms. Reboot once more and leave the device at "Working on updates" without interrupting.
poqexec.exeneeds that window to drain the queue. - Then repair the component store.
DISM /Online /Cleanup-Image /RestoreHealth, thenSFC /ScanNow, in that order. SFC alone cannot repair a store whose own payload is damaged. - Treat deleting the CBS keys and
pending.xmlas a last resort, done knowingly and with a backup. It gets the device installing again, but it abandons an in-flight component transaction: expect to validate the affected KB and to reinstall the package the transaction belonged to.
Markers clean but ConfigMgr still pending. The client's cached state is stale. Trigger the client's own evaluation; never edit registry markers to make the agent happier. That is not where the client stores its state, and you would be lying to five other consumers to satisfy one.
Proof it worked: what a clean device looks like
Verify with the same read-only sweep, not by the device reporting itself compliant.
For reference, here is genuinely clean. Captured read-only from a live Windows 11 corporate device, build 26200.9168, during preparation for this article; all three primary markers were verified absent.
Three things make that a real verification rather than a hopeful one.
Every marker is reported, not just the failing one. A pass is all sources clean at once. Reporting only the marker you chased is how devices get closed out with a second flag still set.
pending.xml is gone, not just the flag. If the flag cleared but the transaction file remains, nothing is fixed and the flag returns on the next boot. That line is the difference between a fix and a reset.
A subsequent update installs. Trigger a scan, confirm an Event 26 followed by a 41, and confirm 0x80240016 is gone.
References
- Microsoft.Windows/RebootPending resource - the five documented causes.
- CheckForPendingReboot.ps1 - CBS
RebootPendingenumerated as a subkey. - MoveFileEx function - how
PendingFileRenameOperationsis written and consumed. - PendMoves and MoveFile (Sysinternals) - the pair format and delete semantics.
- WUA Success and Error Codes (Wuerror.h) - 0x80240016 and 0x00240005.
- DetermineIfRebootPending, CCM_ClientUtilities - ConfigMgr output parameters.
- Analyze log file entries that SFC.exe generates -
%windir%\Logs\CBS\CBS.log. - Troubleshoot unexpected reboots using system event logs - User32 Event 1074.
- Fix Windows Update corruptions and installation failures - DISM and SFC ordering.