HomeNewsletterCommunityMVP FeedToolsArchiveBlogToday's NewsAboutServicesQuick Links Subscribe free
← Back to Blog
Windows Update Windows Updatecatroot2Code SigningCertificatesCryptSvcWinTrustTroubleshootingWindows 11

Windows Update fails signature validation: diagnose catroot2 and the trusted root store before you delete anything

IA
Imran Awan
23 August 2026

A cumulative update downloads cleanly, sits at 100 percent, and then fails with a trust error. Or Windows Update refuses to scan at all. Within about ninety seconds somebody in the thread says: stop Cryptographic Services, delete catroot2, restart. It gets repeated so often that it has stopped sounding like advice and started sounding like a fact.

It is not a fact. It is a mangled version of step 4 of a ten-step Microsoft procedure, and Microsoft's version of that step does not contain the word delete.

The short version

C:\Windows\System32\catroot holds the signed catalog files themselves. catroot2 holds only the database that indexes them. On the lab device that is 7,778 catalogs and 208.8 MB in catroot against a 127 MB catdb in catroot2 - so catroot2 is the derived copy, and catroot is the irreplaceable original. Microsoft's documented reset sequence renames catroot2 to catroot2.bak, gates that step behind "only if everything else failed", and never touches catroot at all. Deleting catroot2 also only addresses one of at least four distinct trust-failure classes, and it destroys the evidence you need to tell them apart. Diagnose first: decode the error, ask the file itself with Get-AuthenticodeSignature, build the chain in isolation, and read the root-CTL sync timestamps out of the registry.

The problem: the package downloads, then refuses to install

This class of failure has two faces, and they look nothing like each other from the console.

The first face is an install-time trust failure. The package transfers fine, so BITS and Delivery Optimization are clearly healthy, and then the handler rejects it. You get codes in the 0x800B or 0x8009 ranges - 0x800B0100, 0x800B0109, 0x80096010 - which are the WinTrust and CryptoAPI facilities, not the Windows Update facility at all.

The second face is a scan that never gets off the ground. The client cannot validate the metadata it just pulled, so it never produces a list of applicable updates. On the lab device the Windows Update client log carries exactly one Event 25 - "Windows Update failed to check for updates with error 0x80240438" - against 344 Event 26 entries and 55 Event 41 entries, which is the shape of a device that scans and downloads normally.

What both faces share is that the failure happens inside signature verification, and signature verification is not part of Windows Update. It is a separate subsystem - WinTrust, CryptoAPI, the catalog database and the certificate stores - that Windows Update merely calls into. That is the single most useful thing to internalise here, because it means every fix aimed at Windows Update components is aimed at the wrong subsystem.

It also means this is a different animal from the payload-missing class. If your error is 0x800f081f, Microsoft documents that as CBS_E_SOURCE_MISSING with the greppable string "ResolveSource() unsuccessful" - the servicing stack could not find bits it needed, which is a component-store problem, not a trust problem. A sibling post in this series covers that one. Do not treat the two as interchangeable just because both end in a failed install.

Watch out. The advice that circulates is "delete catroot2". The procedure Microsoft publishes is Ren %Systemroot%\System32\catroot2 catroot2.bak - a rename, at step 4 of 10, with an explicit instruction to skip step 4 on your first attempt. Those are not the same operation, and the difference is the difference between a reversible change and an irreversible one.

There is a worse variant. Because catroot and catroot2 differ by one character, the instruction gets generalised in retelling to "delete the catroot folders". On the lab device that would remove 7,778 catalog files totalling 208.8 MB, the oldest of which is dated 14 May 2014. Nothing currently installed on that machine is going to put a 2014 catalog back. The catalog database rebuilds itself; the catalogs do not.

Why it happens: catalogs, the catalog database, and the chain to a trusted root

Start with what a catalog actually is, because almost every wrong conclusion in this area comes from not knowing. Microsoft's driver documentation is precise: a catalog file "contains a collection of cryptographic hashes, or thumbprints", and "each thumbprint corresponds to a file that is included in the collection".

So a catalog is a detached signature for a set of files. The individual files are not signed; the catalog is signed, and it vouches for their hashes. That is why a single byte changed in any covered file invalidates the whole thing, and why the same documentation says the system installs catalogs into CatRoot and that "catalog files shouldn't be added to or removed from that directory manually".

You can see this on any Windows binary. Ask PowerShell about wuaueng.dll and it reports SignatureType : Catalog, not Authenticode - the DLL carries no embedded signature of its own, and its trust comes entirely from a catalog sitting in catroot. Microsoft's own cmdlet documentation states the precedence rule outright: "if the file is both embedded signed and Windows catalog signed, the Windows catalog signature is used."

catroot vs catroot2 - real measurement, Windows 11 25H2 build 26200.9168
# The catalogs themselves - the originals PS> Get-ChildItem C:\Windows\System32\catroot -Directory | ForEach-Object { ... } {127D0A1D-4EF2-11D1-8608-00C04FC295EE} files=0 MB=0 {F750E6C3-38EE-11D1-85E5-00C04FC295EE} files=7778 MB=208.8 oldest .cat : 14/05/2014 23:00:40 newest .cat : 19/08/2026 18:19:59 # The database that indexes them - the derived copy PS> Get-ChildItem C:\Windows\System32\catroot2 -Force Mode Length LastWriteTime Name ---- ------ ------------- ---- d----- 15/03/2025 17:42:38 {127D0A1D-4EF2-11D1-8608-00C04FC295EE} d----- 15/03/2025 17:42:38 {F750E6C3-38EE-11D1-85E5-00C04FC295EE} -a---- 10703 23/08/2026 10:31:57 dberr.txt {F750E6C3-...}\catdb 133,169,152 bytes (127.02 MB) {F750E6C3-...}\catdb.jfm 16,384 bytes {127D0A1D-...}\catdb 196,608 bytes {127D0A1D-...}\catdb.jfm 16,384 bytes # Owner of both trees: NT AUTHORITY\SYSTEM

Read those two blocks against each other and the asymmetry is obvious. catroot2 contains two files per subtree: catdb and catdb.jfm. The .jfm extension is the giveaway - that is an ESE flush map, so catdb is a Jet/ESE database whose entire content is derived from the 7,778 files next door.

The service that owns that database is Cryptographic Services, and its own description tells you why it matters to patching. This is the string the service publishes on the lab device, not a paraphrase: it "provides three management services: Catalog Database Service, which confirms the signatures of Windows files and allows new programs to be installed; Protected Root Service, which adds and removes Trusted Root Certification Authority certificates from this computer; and Automatic Root Certificate Update Service, which retrieves root certificates from Windows Update".

Three jobs, one service. Catalog validation, root store writes, and root certificate updates. A single service failure therefore breaks package trust, root management and root refresh simultaneously - which is exactly why trust failures feel so much more catastrophic than they are.

sc.exe qc CryptSvc - real output, healthy idle device
SERVICE_NAME: CryptSvc TYPE : 10 WIN32_OWN_PROCESS START_TYPE : 2 AUTO_START BINARY_PATH_NAME : C:\WINDOWS\system32\svchost.exe -k NetworkService -p DISPLAY_NAME : Cryptographic Services DEPENDENCIES : RpcSs SERVICE_START_NAME : NT Authority\NetworkService ServiceDll : C:\WINDOWS\system32\cryptsvc.dll # Services that depend on CryptSvc: IsoEnvBroker Stopped applockerfltr Stopped AppIDSvc Stopped # wuauserv is NOT in that list - yet it cannot install a package without CryptSvc. # The dependency is functional, not declared. Service Control Manager will # happily leave wuauserv Running with CryptSvc stopped.

Two details there are worth pinning. CryptSvc runs as NetworkService, not LocalSystem, which matters when you are chasing permission errors. And its only declared dependency is RpcSs, because the local catalog client reaches it over RPC - keep that in mind for the error decoding later.

The binaries that do the actual verifying are separate again, and worth naming because the documented repair scripts touch them.

BinaryWhere it livesWhat it does (verified role and file description)
wintrust.dllC:\Windows\System32 (10.0.26100.8972)File description "Microsoft Trust Verification APIs". Exports WinVerifyTrust, the function that decides whether a subject is trusted, plus the CryptCATAdmin* catalog APIs. This is the DLL that produces your 0x800B code.
softpub.dllC:\Windows\System32 (10.0.26100.9168)"Softpub Forwarder DLL" - the Software Publisher trust provider surface. WINTRUST_ACTION_GENERIC_VERIFY_V2, the Authenticode policy action, is defined in Softpub.h.
crypt32.dllC:\Windows\System32"Crypto API32" - certificate stores and chain building. It is also the message resource file for the Microsoft-Windows-CAPI2 event provider, which is how you get readable chain diagnostics.
cryptsvc.dllC:\Windows\System32"Cryptographic Services" - the ServiceDll loaded into the svchost.exe -k NetworkService -p host. This is the process that owns catdb.
mssign32.dllC:\Windows\System32"Microsoft Trust Signing APIs" - the signing-side counterpart to wintrust. Present on clients; you will not normally call it.
wuaueng.dllC:\Windows\System32 (1509.2607.1012.0)"Windows Update Agent" - the ServiceDll for wuauserv. Note the version: it is serviced separately from the OS build, and it is itself catalog-signed, which is why a broken catalog database can stop the agent from loading cleanly.
initpki.dllDoes not exist on 26200.9168Listed in Microsoft's own reset procedure for regsvr32 re-registration. It is not on the disk. More on that in the fix section.

Now the chain. A catalog is signed by a leaf certificate, which is issued by an intermediate, which chains to a root that must be present and trusted in the local machine store. Every hop is a place this can break, and each break has its own error code.

The real signing chain behind a Windows Update binary
PS> $sig = Get-AuthenticodeSignature C:\Windows\System32\wuaueng.dll PS> $sig | Format-List Status, StatusMessage, SignatureType, IsOSBinary Status : Valid StatusMessage : Signature verified. SignatureType : Catalog IsOSBinary : True PS> $ch = New-Object System.Security.Cryptography.X509Certificates.X509Chain PS> $ch.Build($sig.SignerCertificate) Chain built OK : True ; elements = 3 [0] CN=Microsoft Windows, O=Microsoft Corporation NotAfter = 17/10/2026 20:09:15 [1] CN=Microsoft Windows Production PCA 2011, O=Microsoft Corporation NotAfter = 19/10/2026 19:51:42 Thumb=580A6F4CC4E4B669B9EBDC1B2B3E087B80D0678D [2] CN=Microsoft Root Certificate Authority 2010, O=Microsoft Corporation NotAfter = 23/06/2035 23:04:01 Thumb=3B1EFD3A66EA28B16697394703A72CA340A05BD5 TimeStamper : CN=Microsoft Time-Stamp Service, ...

Three elements: leaf, intermediate, root. Break element 2 and you get 0x800B0109, CERT_E_UNTRUSTEDROOT, "a certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider". Break the chain earlier and you get 0x800B010A, CERT_E_CHAINING, "a certificate chain could not be built to a trusted root authority". Those are two different faults with two different fixes, and neither of them is a catroot2 fault.

The root store is kept current by the third of CryptSvc's three jobs. Microsoft documents the mechanism: clients fetch certificate trust lists from ctldl.windowsupdate.com over HTTP on TCP 80, pulling authrootstl.cab (the trusted CTL), disallowedcertstl.cab and disallowedcert.sst (the untrusted CTL and store), and individual <thumbprint>.crt files. Roughly 1.5 MB in total. This traffic is not the same as your Windows Update traffic, and it is routinely missed by proxy allow-lists that were written for *.windowsupdate.com download endpoints only.

Context. An expired certificate in your store is usually not a fault. Microsoft's Authenticode documentation is explicit: "time stamping allows Authenticode signatures to be verifiable even after the certificates used for signature have expired", and conversely "without a time stamp, the signature becomes invalid when the signing certificate expires, and Windows will treat the binary as unsigned". On the lab device the machine Root store holds 73 roots of which 14 are already expired, and the intermediate store still holds CN=Microsoft Code Signing PCA 2011, which expired on 8 July 2026 - 46 days before this measurement. Every update on that device installs. The countersignature is doing its job.

That gives you four failure classes to distinguish, and only one of them has anything to do with the catalog database.

ClassDocumented code and meaningWhat is actually wrong
No signature found0x800B0100 TRUST_E_NOSIGNATURE - "no signature was present in the subject"The catalog covering the file is missing, truncated or not indexed. This is the only class where the catalog store or its database is genuinely implicated.
Untrusted or unbuildable chain0x800B0109 CERT_E_UNTRUSTEDROOT; 0x800B010A CERT_E_CHAININGA root is absent from the store, or an intermediate cannot be found. Root CTL sync failure, a stripped store, or a blocked ctldl path.
Outside validity window0x800B0101 CERT_E_EXPIRED - "not within its validity period when verifying against the current system clock or the timestamp in the signed file"Very often a wrong system clock, not a wrong certificate. Read that message carefully: the clock is named first.
Digest mismatch0x80096010 TRUST_E_BAD_DIGEST - "the digital signature of the object did not verify"; 0x80096002 TRUST_E_NO_SIGNER_CERTThe file's hash no longer matches the thumbprint in the catalog. Corrupt transfer, a filter driver rewriting the file, or genuine tampering.

Three of those four classes are completely untouched by anything you do to catroot2. That is the case against the advice: it addresses one class out of at least four, it cannot tell you which one you are in, and it deletes the evidence that would have told you on the way past.

How to verify: eight checks before you stop a service

Work these in order. Each one is read-only. You should be able to stop at whichever step names your fault.

1. Decode the code, and notice which facility it came from. certutil -error resolves the WinTrust and CryptoAPI facilities properly, which is exactly the range you care about here.

certutil -error - real output, decoding the trust facility
C:\> certutil -error 0x800B0100 0x800b0100 (-2146762496 TRUST_E_NOSIGNATURE) -- 2148204800 Error message text: No signature was present in the subject. C:\> certutil -error 0x800B0109 0x800b0109 (-2146762487 CERT_E_UNTRUSTEDROOT) -- 2148204809 Error message text: A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider. C:\> certutil -error 0x800B0101 0x800b0101 (-2146762495 CERT_E_EXPIRED) -- 2148204801 Error message text: A required certificate is not within its validity period when verifying against the current system clock or the timestamp in the signed file. # And the limit, measured: the Windows Update facility does NOT decode. C:\> certutil -error 0x80242006 0x80242006 (-2145116154) -- 2149851142 (-2145116154) Error message text: Error 0x80242006 (-2145116154) # 0x8024xxxx is WU's own facility. For those you need Microsoft's # published error list - 0x80242006 is WU_E_UH_INVALIDMETADATA.

That last pair matters. If certutil -error gives you a symbolic name, you are in the trust subsystem and this post applies. If it echoes the number back at you, you are in the Windows Update facility and you should be reading the WU error list instead.

2. Check CryptSvc properly. Not just "is it running" - check start type and identity too. The healthy baseline is Running, Automatic, NT Authority\NetworkService, hosted in svchost.exe -k NetworkService -p. A CryptSvc set to Disabled by a hardening baseline is a real and common root cause, and it produces trust failures that no amount of folder renaming will fix.

3. Ask the file itself. This is the step almost everybody skips, and it is the one that settles the argument. Point Get-AuthenticodeSignature at the actual thing that failed - the .msu, the .cab, the .cat, or the binary named in the log. The shipped SignatureStatus enumeration has exactly seven values: Valid, UnknownError, NotSigned, HashMismatch, NotTrusted, NotSupportedFileFormat, Incompatible. HashMismatch and NotTrusted point at two completely different repairs.

4. Build the chain in isolation. If step 3 returned NotTrusted, take the signer certificate out of the signature object and build its chain by hand, as in the block above. X509Chain reports per-element status through X509ChainStatusFlags, and the flag names are the diagnosis: UntrustedRoot, PartialChain, NotTimeValid, NotSignatureValid, RevocationStatusUnknown, OfflineRevocation, ExplicitDistrust. PartialChain means a missing intermediate. UntrustedRoot means a missing or removed root. OfflineRevocation usually means a proxy, not a certificate.

5. Read the root-update state out of the registry. This is the highest-value check in the whole sequence and it takes one command. The automatic root update mechanism records its own last-success timestamps as binary FILETIME values.

HKLM\SOFTWARE\Microsoft\SystemCertificates\AuthRoot\AutoUpdate
ValueMeaningWhat to look for
LastSyncTime8-byte FILETIME of the last successful trusted-CTL sync.Decode it. Lab device: 2026-08-23 10:29:44 UTC, i.e. today. A value weeks or months old on a device that is otherwise online is your root cause.
DisallowedCertLastSyncTimeSame, for the untrusted CTL.Lab device: 10:30:10 UTC, 26 seconds after the trusted CTL. The two sync independently; one can succeed while the other fails.
EncodedCtlThe cached trusted certificate trust list itself.Lab device: 204,123 bytes. Present and large means the device has a real CTL cached. Absent or tiny is a red flag.
DisallowedCertEncodedCtlThe cached untrusted CTL.Lab device: 6,096 bytes. This is the one Microsoft explicitly recommends you never disable.
PinRulesEncodedCtl / PinRulesLastSyncTime / PinRulesLastErrorCertificate pinning rules cache, its sync time, and its last error.Lab device: 17,816 bytes, synced 10:30:48 UTC, and a LastError that decodes to 0x2EFD (12029) - a connect failure - stamped 2026-07-30 07:30:36 UTC. A stale error next to a fresh sync time means the failure already recovered. Do not chase it.
RootDirUrlOverrides the download location for the CTL files.Absent on the lab device, so the default ctldl.windowsupdate.com is in use. If present, the CTL files must actually exist at that path or root updates silently stop.

The policy side lives elsewhere, and it carries a trap worth knowing.

HKLM\SOFTWARE\Policies\Microsoft\SystemCertificates\AuthRoot
ValueMeaningWhat to look for
DisableRootAutoUpdateA value of 1 disables automatic update of the trusted CTL.Absent on the lab device, so root auto-update is on. If it is 1, root updates stopped by policy - and every "delete catroot2" cycle in the world will not bring them back.
EnableDisallowedCertAutoUpdateA value of 1 enables automatic update of the untrusted CTL.Should stay enabled even in disconnected designs. Microsoft recommends against disabling the untrusted CTL specifically.
Subkeys Certificates, CRLs, CTLsWhere policy-delivered trust objects land.These three subkeys exist on a device with no root policy at all - see the gotcha below.
Gotcha. Test-Path 'HKLM:\SOFTWARE\Policies\Microsoft\SystemCertificates\AuthRoot' returns True on the lab device - and that device has no root-certificate policy whatsoever. Measured: ValueCount = 0, SubKeyCount = 3, and the three subkeys are the empty Certificates, CRLs and CTLs containers Windows creates regardless. A detection script that treats key existence as "policy is configured" will report managed root trust on every device in your fleet. Test for the specific value and report the value count.

6. Read dberr.txt - and then refuse to over-read it. The catalog database writes its own error log to C:\Windows\System32\catroot2\dberr.txt. It is genuinely useful, and it is also the single most over-interpreted file in this whole area.

catroot2\dberr.txt on a device where every update installed successfully
# Success lines - one per catalog added, with a duration CatalogDB: 18:29:14 19/08/2026: DONE Adding Catalog File (141ms): Microsoft-Windows-Client-Desktop-Required-Package~31bf3856ad364e35~amd64~en-GB~10.0.26100.9168.cat CatalogDB: 18:29:14 19/08/2026: DONE Adding Catalog File (281ms): Microsoft-Windows-Client-Desktop-Required-Package0011~...~10.0.26100.8972.cat # Error lines - source file and line number, then a Win32 code CatalogDB: 18:03:02 21/08/2026: catdbcli.cpp at line #830 encountered error 0x000006ba CatalogDB: 00:33:40 22/08/2026: catdbcli.cpp at line #830 encountered error 0x000006b5 CatalogDB: 10:31:57 23/08/2026: catadnew.cpp at line #1271 encountered error 0x00000057 # File statistics, measured: total lines : 88 error lines : 47 # 53 percent of the file is errors DONE lines : 38 # Decoded with certutil -error: 0x426 x16 ERROR_SERVICE_NOT_ACTIVE The service has not been started. 0x45b x14 ERROR_SHUTDOWN_IN_PROGRESS A system shutdown is in progress. 0x057 x7 ERROR_INVALID_PARAMETER The parameter is incorrect. 0x6ba x6 RPC_S_SERVER_UNAVAILABLE The RPC server is unavailable. 0x6b5 x4 RPC_S_UNKNOWN_IF The interface is unknown.

Forty-seven error lines. Every August update on this device installed successfully. Decode the codes and the reason is obvious: ERROR_SERVICE_NOT_ACTIVE, ERROR_SHUTDOWN_IN_PROGRESS and the two RPC codes are all what you get when something asks the catalog database a question while CryptSvc is stopping or the machine is shutting down. They are shutdown-race noise, not corruption.

This is the same lesson the CBS.log post in this series lands: an error count is not a verdict. If you are going to cite dberr.txt as your justification for destroying the database, at least decode the errors first - and note that dberr.txt does not appear in any Microsoft product documentation I can find. Its interpretation is entirely community folklore, including the folklore that told you to delete the folder.

7. Check the clock. CERT_E_EXPIRED names the system clock before it names the certificate. A device with a wrong date, a dead CMOS battery, or a broken time source will fail signature validation on perfectly good packages, and will keep failing after you have deleted every folder in System32.

8. Only now, turn on chain logging. Windows ships a detailed certificate-chain diagnostic channel and leaves it off. On the lab device Microsoft-Windows-CAPI2/Operational reports IsEnabled : False with a 1,052,672-byte cap. Enable it in Event Viewer, raise the size first because it fills fast, reproduce the failure, then disable it again. The provider is backed by crypt32.dll and defines 74 events; these are the ones that matter, with task names read from the on-device provider manifest.

Channel: Microsoft-Windows-CAPI2/Operational (disabled by default)
Event IDTask (from the provider manifest)What it tells you
10 / 11Build Chain - Start / StopThe chain-building call itself. Event 11 carries the result, including the chain error status. This is where UntrustedRoot and PartialChain surface with the actual certificates named.
16Inhibit Issuer Certificate Retrieval (Error level)Windows wanted to fetch a missing issuer and was prevented. Strong signal for a proxy or an offline-hardened build, not a corrupt catalog.
17 / 18Retrieve Third-Party Root Certificate from CacheThe root came from the local CTL cache. Healthy path.
19 / 20Retrieve Third-Party Root Certificate from NetworkThe root was fetched live. If these appear and fail, your ctldl.windowsupdate.com path is blocked.
30Verify Chain PolicyPolicy evaluation on a built chain - the step that applies Authenticode-specific rules.
40 / 41 / 42Verify Revocation - Start / Stop; Reject Revocation Information (Error level)Revocation checking. Event 42 at Error level is the classic offline-revocation false alarm behind proxies.
80 / 81Verify Trust - Start / StopThe WinVerifyTrust call as a whole. Event 81 carries the return value you saw in your install log.
82Find Security Catalog for FileThe catroot2 event. This is the catalog lookup. If verification fails and event 82 shows no catalog was found for your file, you have a genuine catalog-store problem. If 82 succeeds and 11 fails, the catalog was found and the chain is your problem - stop thinking about catroot2 entirely.
90X509 ObjectsDumps the certificates involved so you can match thumbprints against your store.
Tip. Event 82 versus event 11 is the whole decision in one comparison. Event 82 answers "was a catalog found for this file". Event 11 answers "did the chain build". Only a failure at 82 justifies looking at the catalog store at all, and even then the repair is servicing, not deletion.

The fix: what Microsoft documents, and what deletion actually costs

Microsoft's manual reset procedure is a ten-step sequence, and the shape of it is the argument. Step 2 stops three services - bits, wuauserv, cryptsvc. Step 3 deletes the BITS queue files. Step 4 is the folder rename, and it comes with an unusually blunt instruction: if this is your first attempt, go to step 5 without doing step 4. Microsoft's own words are that step 4 "should only be performed at this point in the troubleshooting if you can't resolve your Windows Update issues after following all steps but step 4".

Microsoft's documented step 4 - verbatim commands, note the verb
# Step 2 - three services, in this order net stop bits net stop wuauserv net stop cryptsvc # Step 4 - ONLY after everything else has failed. Rename, never delete. Ren %Systemroot%\SoftwareDistribution\DataStore DataStore.bak Ren %Systemroot%\SoftwareDistribution\Download Download.bak Ren %Systemroot%\System32\catroot2 catroot2.bak # Step 9 - bring them back in the same order net start bits net start wuauserv net start cryptsvc # Note what is NOT in the procedure anywhere: catroot. # Note also: no rd, no del, no Remove-Item on catroot2.

The rename is not stylistic caution. It is the rollback. If the reset does not fix your problem - which, given that three of the four failure classes are unrelated to the database, is the likely outcome - you stop the services again, delete the freshly rebuilt catroot2, rename catroot2.bak back, and you are exactly where you started with the evidence intact. Delete instead and that option is gone, along with the dberr.txt history that would have told you which class you were in.

What does a rebuild actually cost? Look again at those dberr.txt success lines: the database logs each catalog individually, with a per-file duration, observed between 0 ms and 281 ms. A full rebuild is 7,778 sequential catalog additions on this device, done by a service running as NetworkService and reached over RPC. That is the mechanism behind the CryptSvc CPU and disk complaints that fill community threads after a catroot2 reset - and to be clear about provenance, those complaints are community reports on Microsoft Q&A, not a documented behaviour. The measured per-catalog timings are the documented-adjacent part; the aggregate impact is inference.

There is one more thing worth knowing before you paste the rest of that procedure into a production console.

Testing Microsoft's regsvr32 re-registration list against 26200.9168
PS> # 36 DLLs are listed in step 6 of the documented reset. Do they exist? Total in Microsoft's list : 36 Present in System32 : 24 MISSING from System32 : 12 Missing files: msxml.dll gpkcsp.dll sccbase.dll slbcsp.dll initpki.dll wuaueng1.dll wucltui.dll wuweb.dll qmgrprxy.dll wucltux.dll muweb.dll wuwebv.dll # One third of the list refers to files that are not on a modern client. # wuaueng1.dll, wucltui.dll, wuweb.dll, muweb.dll, wuwebv.dll and # wucltux.dll are the pre-Windows-10 Windows Update UI and web control. # gpkcsp/sccbase/slbcsp are legacy smart-card CSPs. They are gone. # The ones that DO matter and DO exist: wintrust.dll, softpub.dll, # cryptdlg.dll, wuapi.dll, wuaueng.dll, qmgr.dll.

Twelve of thirty-six regsvr32 lines will fail on a current Windows 11 client, each with its own error dialog or exit code. If you have ever watched that script run and concluded from the error spray that the machine was badly broken, it was not - the procedure is simply older than the OS you ran it on. Say that out loud when a colleague sends you a "Windows Update repair script" that includes all thirty-six.

So what do you actually do, per class?

Untrusted or unbuildable chain. Fix root distribution, not folders. Confirm DisableRootAutoUpdate is not set, confirm ctldl.windowsupdate.com resolves and is reachable on TCP 80, then force a sync. For a disconnected estate, Microsoft documents the two certutil options built for exactly this: Certutil -syncWithWU <destination> pulls the CTL files to a share, and Certutil -generateSSTFromWU <file>.sst produces a serialized store you can distribute by Group Policy. The documented failure codes from that command are themselves diagnostic - 0x80072ee7 means ctldl did not resolve, 0x80072efd means it resolved but would not connect, 0x80070043 means your destination share is wrong.

Outside validity window. Fix the clock and the time source. Nothing else.

Digest mismatch. Re-download the package and check what is touching the file in flight. Microsoft's own guidance for the neighbouring ERROR_SHARING_VIOLATION case points at non-Microsoft filter drivers such as antivirus, and the same suspects apply when a hash stops matching.

No signature found. This is the only one where the catalog store is implicated, and even here the repair is component servicing - DISM /Online /Cleanup-Image /RestoreHealth then sfc /scannow, in that order - because catalogs are installed by the servicing stack and that is what puts a missing one back. Deleting the index does not conjure a missing catalog file.

Gotcha. One place Microsoft does point at catroot2 directly: the documented mitigation for 0x80242006, WU_E_UH_INVALIDMETADATA, "a handler operation couldn't be completed because the update contains invalid metadata". The published fix renames DataStore, Download and catroot2 to .bak. If that is genuinely your code, you have documented cover - and note that even here the documented verb is Ren.

One last piece of hygiene, because it will come up in every trust conversation for the rest of 2026. The intermediate in the measured chain above is Microsoft Windows Production PCA 2011, and it expires on 19 October 2026. Microsoft has published guidance on the 2011-era certificate set expiring through 2026 and the 2023 replacements. That guidance is about Secure Boot and the early boot path, and it says plainly that affected devices "will continue to start and operate normally, and standard Windows updates will continue to install". So: real deadline, real work to plan, but not a cause of Windows Update trust failures. Do not let a colleague pin this month's install error on it.

Proof it worked: a healthy trust path, measured

The wrong success criterion is "no errors anywhere". You have already seen a device with 47 error lines in dberr.txt, 14 expired roots, an expired code-signing intermediate and a stale pin-rules connect failure, on which every update installs. Absence of errors is not the target.

The right criterion is four specific positives, and here they are on the lab device.

Known-good trust baseline - read-only, Windows 11 25H2 build 26200.9168
# 1. The verifier is alive and correctly configured cryptsvc Running / Automatic / NT Authority\NetworkService / depends on RpcSs ServiceDll C:\WINDOWS\system32\cryptsvc.dll wuauserv Running / Manual / LocalSystem # 2. A specific file validates, through a catalog, to a trusted root Get-AuthenticodeSignature wuaueng.dll Status : Valid StatusMessage : Signature verified. SignatureType : Catalog # not Authenticode - proves catroot is being read IsOSBinary : True X509Chain.Build : True (3 elements, terminating at Microsoft Root Certificate Authority 2010) # 3. Root trust is being refreshed, and you can date it LastSyncTime : 2026-08-23 10:29:44 UTC DisallowedCertLastSyncTime : 2026-08-23 10:30:10 UTC EncodedCtl : 204,123 bytes cached DisableRootAutoUpdate : not set RootDirUrl : not set (default ctldl.windowsupdate.com) # 4. Store inventory - context, not a pass/fail LocalMachine\Root 73 (14 already expired - normal) LocalMachine\AuthRoot 41 LocalMachine\CA 27 (incl. Microsoft Code Signing PCA 2011, expired 08/07/2026 - still normal) LocalMachine\Disallowed 0 LocalMachine\TrustedPublisher 70 # The catalog store itself, for the record: catroot 7,778 .cat / 208.8 MB catroot2 catdb 127.02 MB

Check one: CryptSvc Running and Automatic under the right identity. Check two: a named file validating with SignatureType : Catalog and a chain that builds to three elements. That combination proves the catalogs are being found and the chain resolves - which is precisely the pair that events 82 and 11 report, obtained without turning any logging on.

Check three: a LastSyncTime from today. This is the value to collect fleet-wide, because it turns an invisible dependency into a dated fact. A device whose LastSyncTime is three months old is a device whose root trust is frozen, and it will eventually fail to validate something newly signed. That is a proactive finding, not an incident.

Check four is context, not a verdict: fourteen expired roots and a 2026-expired code-signing intermediate are the normal state of a well-maintained Windows 11 device in August 2026.

Then confirm the outcome the way the servicing stack reports it. On this device the Setup log Event 2 records "Package <KB> was successfully changed to the Staged state", and Microsoft-Windows-WindowsUpdateClient/Operational Event 41 records "An update was downloaded" - 55 of them. Those, plus Get-HotFix showing the KB you were fighting, are your proof. Not the absence of lines in dberr.txt.

And if you did end up running the documented reset: verify by renaming your way back. Confirm the update installs, then keep catroot2.bak until the next patch cycle has completed cleanly before you remove it. That is the whole reason Microsoft wrote Ren instead of rd, and it is the reason the internet's favourite version of this fix is the dangerous one.

References

All device measurements in this post were captured read-only on 23 August 2026 from a live Windows 11 Enterprise 25H2 device, build 26200.9168, servicing stack 10.0.26100.9156. Nothing was stopped, renamed or deleted to produce them. Where a fact is Microsoft-documented it is linked above; where it is an on-device observation or an inference from one, it is labelled as such in the text.

Was this post helpful?
React below — no account needed
Share this post
LinkedIn X / Twitter Reddit Bluesky

More from EndpointWeekly

Windows Update
The Windows patching triage decision tree: which log, which key,…
Route each patching symptom to the one evidence source that answers it. Then learn the…
Windows Update
One read-only PowerShell collector for Windows patching failures…
Test-Path and value checks return confidently wrong patching verdicts on real devices.…
Windows Update
Proving a hotpatch actually applied: the build number is the…
In August 2026 the hotpatch put Windows 11 25H2 on build 26200.9106 and the LCU put it on…