HomeNewsletterCommunityMVP FeedToolsArchiveBlogToday's NewsAboutServicesQuick Links Subscribe free
← Back to Blog
Windows Update Windows UpdateFeature UpdateWindows Setupsetuperr.logSetupDiagTroubleshootingPantherWindows 11

A feature update failed and setupact.log is 547 MB: read setuperr.log first

IA
Imran Awan
23 August 2026

A feature update fails. Somebody opens CBS.log, finds nothing that looks like an upgrade, and moves on to Get-WindowsUpdateLog. That produces a few hundred thousand lines of ETW trace with no mention of the failure either. Two hours gone, no root cause.

Both files were the wrong file. Windows Setup keeps its own logs, in its own folders, in its own format, and it does not write to either of those places.

And when admins do find the right folder, the next mistake is worse: they open the biggest file in it.

The short version

A feature update failure is Windows Setup, not CBS and not the Windows Update agent, so the logs live in a Panther folder — and which Panther folder depends on which phase failed. Microsoft documents setuperr.log as the error-only companion to setupact.log, and the size difference is the whole argument: on the device I wrote this on, setupact.log is 573,433,781 bytes across 2,688,076 lines and setuperr.log is 9,099 bytes across 63 lines. Same upgrade. A 63,022:1 reduction. Read the small one first, anchor on the last occurrence of the result code — Microsoft's own words are that "the last failure in the log file is typically the fatal error, not the first one" — and only then go into the big file, at the timestamp the small file gave you.

The problem: the failure log is 547 MB and you have twenty minutes

Here is the actual state of C:\Windows\Panther on the Windows 11 Enterprise 25H2 device (build 26200.9168) I used to write this. Fifty-two files, 934.2 MB in total. I sorted by size and took the top of the list.

PowerShell — real output, read-only
# Get-ChildItem C:\Windows\Panther -File | Sort Length -Desc | Select Name,Length,LastWriteTime Name Length LastWriteTime ---- ------ ------------- setupact.log 573433781 3/15/2025 6:04:20 PM MigLog.xml 336444054 3/15/2025 5:46:50 PM WinSetupMon.log 11924452 3/15/2025 5:46:55 PM diagwrn.xml 2901430 3/15/2025 5:58:24 PM setup.etl 1552384 3/15/2025 5:58:24 PM diagerr.xml 38472 3/15/2025 5:58:24 PM setuperr.log 9099 3/15/2025 5:58:12 PM <-- this one # 52 files, 934.2 MB total in that one folder

Two files account for 93 percent of it. setupact.log at 547 MB and MigLog.xml at 321 MB. Notepad will open the first one eventually. Ctrl+F in it will not be a pleasant experience.

And 9,099 bytes down the list is the file that actually names the failure.

Same upgrade, same folder — measured bytes, linear scale
setupact.log
573,433,781
MigLog.xml
336,444,054
WinSetupMon.log
11,924,452
setuperr.log
9,099
The green sliver is drawn at 0.4% so it renders at all. Its true share is 0.0016% of setupact.log. That is not a rounding error — it is the entire point of the file.

By line count the gap is slightly less extreme and slightly more useful, because lines are what you actually read. I counted both with a StreamReader rather than Get-Content, because loading 547 MB into a PowerShell array is its own outage.

Measuresetupact.logsetuperr.logReduction
Bytes573,433,7819,09963,022:1
Lines2,688,0766342,668:1
Timestamped entries at Error level72501.4:1
Time to read end to endNot a real optionAbout 30 seconds

Look at the third row for a moment, because it is the one nobody expects. setupact.log contains 2,688,076 lines. Exactly 72 of them are logged at Error level. Everything else is Info (2,544,217) or Warning (6,802). You are hunting 72 needles in a 2.7-million-line haystack, and there is a 63-line file sitting next to it that already did the hunting.

Watch out: the reflex fixes for this failure class destroy the evidence. Clearing SoftwareDistribution does nothing for a Setup failure because Setup does not read it. Running sfc /scannow writes its [SR] entries into CBS.log, which is a different log about a different subsystem. Worst of all, retrying the upgrade overwrites $Windows.~BT\Sources\Panther — the folder holding the down-level logs for the attempt that just failed. Copy the whole folder tree out before you retry anything. Once it is gone, you are diagnosing the retry, not the failure.

So before any command, three questions need answers.

  1. Which phase failed, because that decides which folder holds the relevant log?
  2. What is the result code and the extend code, and where can I still recover them?
  3. Which of the errors in the file is the one that actually killed the upgrade, as opposed to noise that a successful upgrade would also have produced?

Question three is not rhetorical. I will show you a setuperr.log from a successful upgrade that contains 0x8007042B — the exact result code Microsoft uses in its own failure walkthrough.

Why it happens: Setup has its own logging stack, and it moves

Windows Setup is a different program from Windows Update

A cumulative update is applied by the component-based servicing engine. It logs to CBS.log. A feature update is applied by Windows Setup, which orchestrates CBS as one of several subordinate engines and logs to its own files in its own format. The Windows Update agent's job ends when the payload is on disk and setup.exe is invoked.

That is why CBS.log looks unhelpful during a feature-update failure. It is not that CBS was silent; it is that CBS is one chapter and you are looking for the plot. In my 547 MB setupact.log, 1,302,873 lines carry the CBS tag — nearly half the file. Setup swallowed CBS's logging whole and inlined it. The interesting lines are the other half.

Microsoft documents four phases plus an uninstall phase, with a reboot between each, and each phase has its own failure signature.

PhaseWhat it does (documented)Documented failure character
Down-levelRuns inside the old OS. Windows files copied, installation components gathered."Because this phase runs on the source OS, upgrade errors aren't typically seen."
SafeOSBooted into Windows PE. Recovery partition configured, files expanded, updates installed, rollback prepared."Errors most commonly occur during this phase due to hardware issues, firmware issues, or non-microsoft disk encryption software." Example codes 0x2000C, 0x20017.
First bootInitial settings applied under the new OS."relatively rare, and almost exclusively caused by device drivers." Example codes 0x30018, 0x3000D.
Second boot (OOBE)Final settings applied. Reaches 100 percent here."most commonly due to anti-virus software or filter drivers." Example codes 0x4000D, 0x40017.
UninstallOnly runs if the upgrade was unsuccessful.Example codes 0x50000, 0x50015.
Context: Microsoft also documents a volatile progress key at HKLM\System\Setup\mosetup\volatile\SetupProgress, holding a binary value from 0 to 100. It exists only during the upgrade. That makes it useless for post-mortem work but genuinely useful if you are watching a fleet mid-flight and want to know whether a device is stuck or just slow.

The log locations, and why they move

This is the part that sends people to the wrong file. There is no single setupact.log. There are five documented locations, and the one you want depends on which phase failed. Here is Microsoft's table, condensed.

Log filePhase and documented locationWhen to use it
setupact.logPre-initialization (before down-level): Windows"If setup fails to launch."
setupact.logDown-level: $Windows.~BT\Sources\Panther"All downlevel failures and starting point for rollback investigations."
setupact.logRollback: $Windows.~BT\Sources\Rollback"Investigating generic rollbacks - 0xC1900101."
setupact.logOOBE: $Windows.~BT\Sources\Panther\UnattendGCOOBE-phase rollbacks and operations 0x4001C to 0x4001F.
setupact.logPost-upgrade (after OOBE): Windows\Panther"Investigate post-upgrade related issues."
setuperr.logSame as setupact.log"Review all errors encountered during the installation phase."
miglog.xmlPost-upgrade: Windows\Panther"Identify post upgrade data migration issues."
BlueBox.logDown-level: Windows\Logs\MosetupCommunication between setup.exe and Windows Update. WSUS and WU down-level failures, 0xC1900107.
setupmem.dmp, setupapi.dev.log, *.evtx$Windows.~BT\Sources\RollbackBug check during upgrade; device install issues (0x30018); generic rollbacks.

Read the mechanism behind that table and it stops being something to memorise. $Windows.~BT is Setup's working directory on the source OS. While the down-level phase runs, that is where logging goes. If the upgrade completes, the whole thing is migrated into C:\Windows\Panther on the new OS. If it rolls back, a Rollback sibling folder appears.

So the existence and freshness of these folders is itself diagnostic, before you read a single line.

Down-level logs present, no Rollback folder
$Windows.~BT\Sources\Panther exists · $Windows.~BT\Sources\Rollback absent
Setup failed or was cancelled before it ever reached the point of needing to roll back. Almost always a down-level or pre-flight problem. This is exactly what I found on my device.
Rollback folder present
$Windows.~BT\Sources\Rollback\setupact.log + setupmem.dmp
Setup got far enough to commit and then reversed. This is the 0xC1900101 territory Microsoft describes as "generic" and usually driver-related.
Windows\Panther fresh, no $Windows.~BT at all
C:\Windows\Panther\setupact.log dated to the attempt
The upgrade completed. If the user is still complaining, the problem is post-upgrade, and miglog.xml becomes relevant.
Gotcha: a fresh timestamp on a Panther log does not prove a recent setup ran. On my device, C:\Windows\Panther\UnattendGC\setupact.log was last written today — and its tail is [svchost.exe] Enter WinReIsWimBootEnabled, a WinRE state check, not Windows Setup. Meanwhile the setuperr.log beside it is 0 bytes and dated to the original upgrade. Check the content and the date inside the last entry, not the file's LastWriteTime.

The log entry format, including the field Microsoft does not document

Microsoft documents four elements in a setupact.log or setuperr.log entry: the date and time, the log level (Info, Warning, Error, Fatal Error), the logging component, and the message.

In practice there is a fifth, optional field. A bracketed hex message identifier can appear between the level and the component. Measured on my 50-entry setuperr.log: 16 entries carried one, in the form [0x0808fe]. Any regex you write to parse these files must treat that field as optional, or it will silently mis-assign the component tag on a third of your lines.

setuperr.log — real lines from C:\Windows\Panther, annotated
# Four fields — no message id: 2025-03-15 16:15:29, Error DU DU::CDUSession::Search: Failed to set WU internal configuration property for targeted scans. hr = 0x80070057 ^date/time ^level ^(no id) ^tag ^message # Five fields — optional [0x......] message id present: 2025-03-15 16:48:49, Error [0x08097b] MIG Abandoning apply due to error for object: HKCU\Software\Zscaler ^date/time ^level ^message id ^tag ^message # And two lines in the file carry NO component tag at all: 2025-03-15 16:48:49, Error Apply failed. Last error: 0x00000000 2025-03-15 17:41:54, Error [SetupPlatform.exe] System disks found

Those last two are worth noticing. Apply failed. Last error: 0x00000000 is untagged, and its "last error" is zero. A naive parser reads that as the fatal line and reports a success code as the cause. It is a summary line, not a diagnosis. This is precisely why you anchor on the result code from the phase, not on whatever line happens to say "failed".

The component tags, checked against reality

Microsoft lists nine logging components: CONX, MOUPG, PANTHR, SP, IBSLIB, MIG, DISM, CSI, CBS. It then singles out three: "The logging components SP (setup platform), MIG (migration engine), and CONX (compatibility information) are useful for troubleshooting Windows Setup errors."

I histogrammed all 2,688,076 lines of my setupact.log against that list. All nine are real and all nine are present.

TagMeaningLines in my 547 MB setupact.log
CBSComponent-based servicing — the same engine that writes CBS.log1,302,873
MIGMigration engine — user and system state626,201
SPSetup platform — the operation queue that drives the upgrade217,094
CONXCompatibility information (Appraiser, compat blocks)53,718
CSIComponent servicing infrastructure — CBS's lower layer48,994
DISMDeployment image servicing, including its providers14,671
MOUPGModern setup / setuphost — the outermost orchestration layer7,221
PANTHRPanther logging infrastructure itself114
IBSLIBImage-based setup library40

Microsoft's list is accurate. It is also incomplete. Four more tags appear in real volume and are not in the documented nine.

Undocumented tagLines observedWhat it is doing there
SXS237,678Side-by-side assembly resolution. Third largest tag in the entire file, and absent from the documented list.
DPX2,745Delta/package expansion. Also named in the SetupDiag rule UpdateAgentExpanderFailure, which matches "DPX expander failures in the downlevel phase".
SYSPRP1,590Sysprep operations. SetupDiag has a matching rule, SysPrepLaunchModuleFailure.
TOOL476External tool invocation from within Setup.
Context: the same "documented list is a subset" caveat applies to the Windows Update ETW component tags. If you decode a real WU trace you will find WebServices, Deployment, Metadata, Shared, Reporter, SLS and Driver alongside the published ones. In both stacks, treat Microsoft's tag list as a guide to the important tags rather than an exhaustive schema. Never build a parser that discards lines whose tag it does not recognise.

The binaries that write these lines

Tags are not abstractions. Each one is a component with a file on disk, and knowing which file lets you check versions when a phase misbehaves. Everything below I verified on the device rather than assumed.

BinaryVerified location and versionRole
SetupPlatform.exeC:\Windows\System32\oobe\SetupPlatform\ — 10.0.26100.3476, description "SetupPlatform module", 357,816 bytesOwns the SP tag. Drives the operation queue. When you see CSetupPlatformPrivate::Execute: Execution of operations queue failed, abandoning, this is the process saying it.
UNBCL.DLLSame folder — 10.0.26100.3476, description "Unmanaged BCL", 1,090,976 bytesSetup's base class library. Its fingerprints show up inside error text: one of my MIG errors names class UnBCL::XmlNode in an XML parse failure.
AppxProvider.dllC:\Windows\System32\Dism\ — not System32 proper — 10.0.26100.8457, "DISM App Package (.appx) Provider"A DISM provider. Source of all 22 DISM-tagged error lines in my file. Remember this one; it is the punchline later.
migisol.dllC:\Windows\System32\ — 10.0.26100.8972, "Migration System Isolation Layer"Isolation layer for the migration engine, so a badly behaved plug-in cannot take the whole engine down.
IasMigPlugin.dllC:\Windows\System32\ — 10.0.26100.5074, "NPS Migration DLL"An individual migration plug-in. Named by full path in my setuperr.log, which is what makes MIG errors actionable — the log tells you which DLL failed.
wimmount.sysC:\Windows\System32\drivers\ — 10.0.26100.8972, "Wim file system Driver"Mounts the install image. Two SetupDiag rules exist purely for its failure modes: WimMountDriverIssue and PreReleaseWimMountDriverFound.
SetupDiag.exeExtracted to %SystemDrive%\$Windows.~bt\Sources during upgrade; moved under Windows.old afterwardsParses these logs for you. Not present on my deviceWindows.old has been cleaned up, and Microsoft documents that removing it removes SetupDiag too.
Tip: before you read anything by hand, run SetupDiag. Microsoft is unambiguous: "Use the SetupDiag tool before you begin manually troubleshooting an upgrade error." It is shipped inside Windows Setup, and if the upgrade fails it runs itself with /Output:%windir%\logs\SetupDiag\SetupDiagResults.xml and /RegPath:HKEY_LOCAL_MACHINE\SYSTEM\Setup\SetupDiag\Results. Check for that output before you download anything — the answer may already be on the box. It was on mine.

Result codes and extend codes

An unsuccessful Setup returns two codes, and you need both. A result code, corresponding to a Win32 or NTSTATUS error, and an extend code carrying "information about both the phase in which an error occurred, and the operation that was being performed". They are reported as a pair, for example 0xC1900101 - 0x4000D.

The extend code decodes positionally: first digit is the phase, last two digits are the operation.

First digitPhase constantWhich folder to open
0SP_EXECUTION_UNKNOWNStart with C:\Windows\setupact.log (pre-initialization).
1SP_EXECUTION_DOWNLEVEL$Windows.~BT\Sources\Panther
2SP_EXECUTION_SAFE_OS$Windows.~BT\Sources\Panther, then the Rollback folder.
3SP_EXECUTION_FIRST_BOOTWindows\Panther and Windows\Panther\NewOS.
4SP_EXECUTION_OOBE_BOOT$Windows.~BT\Sources\Panther\UnattendGC, then Windows\Panther.
5SP_EXECUTION_UNINSTALL$Windows.~BT\Sources\Rollback

The operation is the low byte, from a documented list of 33 values. 0D is SP_EXECUTION_OP_MIGRATE_DATA, 0C is SP_EXECUTION_OP_APPLY_IMAGE, 07 is SP_EXECUTION_OP_INSTALL_DRIVERS, 02 is SP_EXECUTION_OP_DOWNLOAD_UPDATES. Microsoft's worked example: "An extend code of 0x4000D, represents a problem during phase 4 (0x4) with data migration (000D)."

Gotcha: that extend-code table carries a version warning that people skip. Microsoft's own note: "Extend codes reflect the current Windows 10 upgrade process, and might change in future releases of Windows 10. The codes discussed in this section apply to Windows 10 version 1607." My device is build 26100/26200. I will show you an extend code from it later that decodes to one phase while every other artefact in the log says a different one. When they disagree, believe the log's own phase text, not a table pinned to 1607.

How to verify: a triage order that starts at 9 KB

Here is the order. Each step is cheap, each step narrows the next, and nothing in it modifies the machine.

Step 1 — Establish the phase before you open any log

Test for the folders. This takes a second and tells you which of five setupact.log files matters.

PowerShell — real output from my device, read-only
# Which Setup log folders exist? This IS the phase question. C:\Windows\Panther True C:\Windows\Panther\NewOS True # exists but holds no log files C:\Windows\Panther\UnattendGC True C:\$Windows.~BT True # <-- a prior attempt left this behind C:\$Windows.~BT\Sources\Panther True # <-- DOWN-LEVEL logs are here C:\$Windows.~BT\Sources\Rollback False # <-- never got as far as rolling back C:\Windows\Logs\Mosetup True C:\Windows\Logs\SetupDiag True # <-- SetupDiag already ran itself C:\Windows.old False # cleaned up; SetupDiag.exe went with it # What survived inside $Windows.~BT after cleanup: C:\$Windows.~BT\Sources\ -> Diagnostics\, Panther\ # payload gone, logs kept

That output is a diagnosis on its own. Down-level logs present, no rollback folder, and a $Windows.~BT tree stripped of everything except the log folders. Setup failed early, and Windows deliberately preserved the evidence while reclaiming the space.

Step 2 — Recover the result and extend code, from whichever source still has it

There are three documented places the code pair lives, and they decay at different rates. Try them in this order.

2a. The Windows Error Reporting event. Microsoft documents that when Setup fails, the result code and extend code "are recorded as an informational event in the Application log by Windows Error Reporting as event 1001. The event name is WinSetupDiag02." Ten parameters are listed; P5 is the result error code and P6 the extend error code.

Log channel: Application (Event Viewer → Windows Logs → Application)
Event IDMessage / event nameWhat it tells you
1001Event name WinSetupDiag02, ten parameters P1–P10The authoritative code pair. P4 install result (0=Success, 1=Failure, 2=Cancel, 3=Blocked), P5 result code, P6 extend code, P2 setup mode (1=Downlevel, 5=Rollback), P7/P9 source and new OS build.
1001Event name WinSetupDiag01Same role on legacy operating systems. Search for both names, not just the newer one.
1001Any other WER report bucketWhy filtering on the ID alone fails. 1001 is a shared, high-traffic WER event. I checked the 400 most recent 1001 events on my device: zero were WinSetupDiag. Filter on the event name.

Microsoft's own caveat on this route is easy to miss: "The following Event logs are only available if Windows was updated from a previous version of Windows to a new version of Windows." And there is a second, harsher limit that nobody documents — the Application log rolls.

PowerShell — why the WER route was a dead end here
# Get-WinEvent -ListLog Application RecordCount : 32720 MaximumSizeInBytes : 20971520 # Get-WinEvent -LogName Application -Oldest -MaxEvents 1 Oldest record : 06/27/2026 14:35:08 # The failed upgrade on this device was 2025-05-14. # The Application log only reaches back to 2026-06-27 — a ~2 month window. # The WinSetupDiag02 event for a 15-month-old failure is long gone. # Matching events found: 0

2b. The SetupDiag registry key. This is the route that survived. A 20 MB circular event log wraps in weeks; a registry value does not.

Parent key: HKLM\SYSTEM\Setup
Value / subkeyMeaningWhat to look for
SetupDiag\ResultsWhere Setup writes SetupDiag output when it runs it automatically after a failure.ProfileName (the matched rule), FailureDetails (the code pair), UpgradeStartTime/UpgradeEndTime. Persists indefinitely. Check here first.
MoSetup\Volatile\SetupDiagThe default /RegPath when you run SetupDiag manually without specifying one.Present only after a manual run. Absent on my device — proof that the results I found came from Setup's own automatic invocation, not from someone poking at it.
MoSetup\Volatile\SetupProgressBinary progress value, 0–100, documented as existing only during an upgrade.Useful live, useless post-mortem. Its absence confirms no upgrade is currently in flight.

2c. The log itself. If both of the above are gone, setupact.log records the code pair in plain text as Setup hands it to WER and to Windows Update. On my device the down-level log contains all three of these, and they agree.

$Windows.~BT\Sources\Panther\setupact.log — real lines, code pair recovered from the log
L617: 2025-05-14 11:24:18, Info MOUPG MoSetupPlatform: Setting Watson bucketing parameter -> [4]=[0x800704C7] L695: 2025-05-14 11:24:18, Info MOUPG CSetupDiagnostics: Tracing Data [CUSTOM] -> [Downlevel] -> [Media360][...][Cancelled][Windows 11 Enterprise][26100] [1][2][0x800704c7][0x40004][26100] L748: 2025-05-14 11:24:32, Info MOUPG SetupNotify: Specifying extended data [0x40004] for error [0x800704C7]. L749: 2025-05-14 11:24:32, Info MOUPG SetupHost: Reporting error event -> [0x800704C7, 0x40004] ^result code ^extend code # L749 is the exact (P5, P6) pair the WER doc describes — in the log, # at Info level, so setuperr.log does NOT contain it. That is the one # thing the small file cannot give you.
Tip: that greppable string Reporting error event -> is worth putting in your runbook. It is logged at Info level, which means it is invisible in setuperr.log and survives in setupact.log even when the WER event has aged out and nobody ran SetupDiag. Two anchors, one command: search setupact.log for Reporting error event and for Setup360Result.

Step 3 — Read setuperr.log end to end. All of it.

This is the step that does not exist in most people's process, because they have never noticed the file. It takes thirty seconds and it usually ends the investigation.

Microsoft's documented procedure is ten steps. Compressed, with the reasoning that makes each one make sense:

  1. Get the Setup error code (step 2 above).
  2. Use the extend code's phase digit to pick the folder.
  3. Open the log in a text editor.
  4. Search for the result code and find the last occurrence. Microsoft spells out the mechanics: go to the bottom of the file, then Find with Direction set to Up.
  5. From that last occurrence, "scroll up a few lines from this location in the file and review the processes that failed before generating the result code".
  6. Search for two specific strings: Shell application requested abort and Abandoning apply due to error for object.
  7. Decode the Win32 errors in that region.
  8. Write down the timestamps.
  9. Search the other logs at those timestamps.

Step 4 is the one that matters most, and it is the opposite of instinct. You do not want the first error. Microsoft states it plainly in the SetupDiag documentation: "When SetupDiag indicates that there were multiple failures, the last failure in the log file is typically the fatal error, not the first one."

The reason is architectural. Setup unwinds. A failure deep in a migration plug-in propagates upward through the operation queue, and each layer logs the same code on its way out. The outermost frame is the last line written and the one that describes what Setup actually gave up on.

Step 4 — Only now open setupact.log, at the timestamp you already have

By this point you have a phase, a code pair, a component tag and a timestamp accurate to the second. That turns 2,688,076 lines into a twenty-line window. Open the big file, jump to that second, read the Info lines either side of it. The Info lines are where the context lives — which object, which plug-in, which registry hive.

Context: and here is the measurement that justifies the whole ordering. Microsoft tells you to grep the log for Shell application requested abort and Abandoning apply due to error for object. I counted both across all 573,433,781 bytes of setupact.log: each appears exactly once. Both of those single occurrences are also in the 9,099-byte setuperr.log. Both of the documented text-string searches, on this device, could have been satisfied by reading the small file.

The fix: anchor on the last result code, then widen

The fix in this post is a reading order, not a repair. That is deliberate. Every repair for a feature-update failure — remove the driver, delete the profile, uninstall the agent, free the disk — depends entirely on which one it is, and the logs are how you find out. Guessing the repair is how a two-hour job becomes a two-week one.

What setuperr.log leaves out, exactly

Before you trust the small file, you should know its blind spots. So I diffed them: every Error-level entry in setupact.log, checked for presence in setuperr.log.

Component tagError entries in setupact.logPresent in setuperr.logDropped
MIG22220
DISM22022
SP15150
CONX990
MOUPG110
DU110
untagged220
Total725022

The filter is not "level equals Error". Twenty-two entries were dropped, and every single one of them was DISM-tagged. Here is what they were.

setupact.log — one of the 22 Error lines setuperr.log excluded
2025-03-15 16:43:49, Error DISM DISM Appx Provider: PID=4248 TID=16340 onecore\admin\appmodel\utilities\provisionhelper\msixpackageadapter.cpp(632)\ AppxProvider.dll!00007FFF0E5E5EE9: (caller: 00007FFF0E5E536C) LogHr(1) tid(3fd4) 80070002 The system cannot find the file specified. # All 22 dropped lines came from AppxProvider.dll — verified on disk at # C:\Windows\System32\Dism\AppxProvider.dll (10.0.26100.8457, # "DISM App Package (.appx) Provider") # All 22 were 0x80070002 ERROR_FILE_NOT_FOUND from a provisioned-app lookup. # The upgrade SUCCEEDED. These are exactly the noise a filtered view # is supposed to remove — and it removed them.

So setuperr.log is a curated view, not a mechanical grep for the word "Error". On this device the curation was correct: it kept every SP, MIG, CONX, MOUPG and DU entry — including all three of the tags Microsoft names as the useful ones — and discarded a repetitive DISM provider channel that had nothing to do with the outcome.

Watch out: the corollary is the one real trap in this whole approach. An empty or unhelpful setuperr.log does not mean there is nothing wrong. If the failure lived in a channel the filter drops — a DISM provider, a CBS sub-operation — the small file will be quiet while the upgrade fails. In that case go to setupact.log and search for the result code directly, and check CBS.log for the same timestamp window. Use setuperr.log to accelerate triage, never to conclude it.

Which log answers which question

This is the table I wish I had had the first time. It is the routing layer between a symptom and a file.

QuestionRead thisWhy not the obvious one
What error did Setup give up on?setuperr.log in the phase foldersetupact.log has the same answer buried in 2.7 million lines.
What was Setup doing when it failed?setupact.log at the timestamp from setuperr.logThe context is at Info level, so setuperr.log cannot show it.
What is the result + extend code pair?WER event 1001 WinSetupDiag02, else HKLM\SYSTEM\Setup\SetupDiag\Results, else grep setupact.log for Reporting error eventThe WER event ages out with the Application log. The registry key does not.
Which user or system data failed to migrate?miglog.xml in Windows\Panther321 MB on my device. Only open it once setuperr.log has told you it is a MIG problem.
Did the client ever get the right payload from WSUS or WU?BlueBox.log in Windows\Logs\MosetupDocumented as the setup.exe-to-Windows-Update conversation. The one to open for 0xC1900107.
Did a driver fail to install during the upgrade?setupapi.dev.log in the Rollback folderDocumented for device install issues, 0x30018.
Did the machine bug check mid-upgrade?setupmem.dmp in $Windows.~BT\Sources\Rollback or %WinDir%\Panther\NewOS\RollbackSetup extracts a minidump specifically so you can debug it. SetupDiag can debug it for you with /LogsPath.
Did a cumulative update fail, not a feature update?CBS.logDifferent engine entirely. And an error count in CBS.log is not a verdict — I have measured a successful cumulative update that logged 715 error-level CSI and SXS entries.
Did the WU agent fail before Setup ever launched?The ETW traces under C:\Windows\Logs\WindowsUpdate\, via Get-WindowsUpdateLogC:\Windows\WindowsUpdate.log is a ~276-byte stub pointing at that cmdlet. And -ForceFlush stops the Update Orchestrator and Windows Update services, so never make it your first command.

Decoding the codes you find

Microsoft's rule: first hex digit 8 means a Win32 error code, C means an NTSTATUS value; take the last four digits and look them up. In practice certutil -error does that lookup for you — for some families. I measured which.

certutil -error — real output, and its real limits
# Works — FACILITY_WIN32 codes decode cleanly: 0x800704c7 (WIN32: 1223 ERROR_CANCELLED) -- The operation was canceled by the user. 0x8007042b (WIN32: 1067 ERROR_PROCESS_ABORTED) -- The process terminated unexpectedly. 0x8007139f (WIN32: 5023 ERROR_INVALID_STATE) -- The group or resource is not in the correct state... 0x80070057 (WIN32: 87 ERROR_INVALID_PARAMETER) -- The parameter is incorrect. 0x570 (WIN32: 1392 ERROR_FILE_CORRUPT) -- The file or directory is corrupted and unreadable. # FAILS — the Setup-specific families are not in any message table: 0xc1800104 -- Error 0xc1800104 (-1048575740) # no name, no text 0xc180010a -- Error 0xc180010a (-1048575734) # no name, no text 0xc1900101 -- Error 0xc1900101 (-1047527167) # the famous rollback code! 0xc1900107 -- Error 0xc1900107 (-1047527161) 0x40004 -- Error 0x40004 (262148) # extend codes never decode # So: certutil for the 0x8007xxxx family. For 0xC18xxxxx / 0xC19xxxxx, # the documented tables are the only source. Do not invent meanings.

That last point deserves emphasis. 0xC1900101 is the single most-searched Windows upgrade code and certutil cannot say a word about it. Microsoft documents it directly instead: "A result code of 0xC1900101 is generic and indicates that a rollback occurred. In most cases, the cause is a driver compatibility issue." The instruction is to analyse the extend code to find the phase — which brings you straight back to picking the right folder.

Proof it worked: two setuperr.log files from one device

Everything so far is documentation plus measurement. Now the two cases that make the argument, both from the same machine.

Case A — the failure, in 21 lines

C:\$Windows.~BT\Sources\Panther on my device holds logs from 2025-05-14. That is fifteen months after the successful upgrade whose logs sit in C:\Windows\Panther. Two different events, two different folders, and the small folder is the failure.

FileBytesLinesDatedOutcome
C:\Windows\Panther\setupact.log573,433,7812,688,0762025-03-15Succeeded
C:\Windows\Panther\setuperr.log9,099632025-03-15Succeeded
C:\$Windows.~BT\Sources\Panther\setupact.log88,3147782025-05-14Failed
C:\$Windows.~BT\Sources\Panther\setuperr.log2,666212025-05-14Failed

An admin investigating the May failure who opens C:\Windows\Panther\setupact.log — the obvious file, the biggest file, the one every article names — is reading 547 MB about a successful upgrade from two months earlier. Meanwhile the failure is fully described in a 2,666-byte file in a hidden folder.

Here is that file, essentially complete.

C:\$Windows.~BT\Sources\Panther\setuperr.log — 21 lines, all real, all MOUPG
2025-05-14 11:24:17, Error MOUPG CSetupResponseTemplate<class IDlpResponse>:: OnCancel(240): Result = 0x800704C7 2025-05-14 11:24:17, Error MOUPG CSetupResponseTemplate<class IDlpResponse>:: ExecuteRoutine(142): Result = 0x800704C7 2025-05-14 11:24:17, Error MOUPG CDlpResponseImpl<...>::Execute(1973): Result = 0x800704C7 2025-05-14 11:24:17, Error MOUPG CDlpActionImpl<...>::ExecuteResponse(1398): Result = 0x800704C7 2025-05-14 11:24:17, Error MOUPG CDlpActionDU::ExecuteDUSetup(2391): Result = 0x800704C7 <-- Dynamic Update 2025-05-14 11:24:17, Error MOUPG CDlpActionDU::ExecuteRoutine(455): Result = 0x800704C7 2025-05-14 11:24:17, Error MOUPG CDlpTask::ExecuteAction(3334): Result = 0x800704C7 2025-05-14 11:24:17, Error MOUPG CDlpTask::ExecuteActions(3487): Result = 0x800704C7 2025-05-14 11:24:17, Error MOUPG CDlpTask::Execute(1643): Result = 0x800704C7 2025-05-14 11:24:17, Error MOUPG CSetupManager::ExecuteTask(3117): Result = 0x800704C7 2025-05-14 11:24:17, Error MOUPG CSetupManager::ExecuteInstallMode(1048): Result = 0x800704C7 2025-05-14 11:24:17, Error MOUPG CSetupManager::ExecuteDownlevelMode(610): Result = 0x800704C7 <-- DOWN-LEVEL, in text 2025-05-14 11:24:17, Error MOUPG CDlpActionImpl<...>::GetResults(742): Result = 0x8007139F <-- different code 2025-05-14 11:24:17, Error MOUPG CSetupManager::GetDUSetupResults(8466): Result = 0x8007139F 2025-05-14 11:24:32, Error MOUPG CDlpTask::Cancel(991): Result = 0xC1800104 2025-05-14 11:24:32, Error MOUPG CDlpTask::Cancel(995): Result = 0xC180010A 2025-05-14 11:24:32, Error MOUPG CDlpTask::Cancel(991): Result = 0xC1800104 2025-05-14 11:24:32, Error MOUPG CSetupManager::Execute(346): Result = 0x800704C7 2025-05-14 11:24:32, Error MOUPG CSetupHost::Execute(517): Result = 0x800704C7 ^^^ LAST occurrence — the outermost frame

This is what "the last failure is typically the fatal error" looks like in the wild. Twenty-one lines, one component tag, and a single result code propagating up a call stack from OnCancel to CSetupHost::Execute. The last line is the outermost frame and confirms what Setup surfaced. The useful lines are the two named ones in the middle: CDlpActionDU::ExecuteDUSetup tells you it died in Dynamic Update, and CSetupManager::ExecuteDownlevelMode tells you the phase in plain English.

Note also that not every line carries the same code. Two lines report 0x8007139F (ERROR_INVALID_STATE) and two report the undecodable 0xC1800104 / 0xC180010A. If you had anchored on the first error, or on whichever error looked most exotic, you would have chased the wrong one. Anchoring on the last occurrence of the code the phase reported keeps you honest.

SetupDiag had already answered it, on disk, unprompted

And then the part that reframes the whole exercise. Setup ran SetupDiag itself when this failed, fifteen months ago, and left the answer in the registry and in a 1,081-byte XML file.

HKLM\SYSTEM\Setup\SetupDiag\Results — real, read-only
ProfileName : FindAbruptDownlevelFailure ProfileGuid : 55882B1A-DA3E-408A-9076-23B22A0472BD SetupDiagVersion : 1.7.0.0 DateTime : 05/14/2025 11:24:41 FailureDetails : ErrorCode = 0x800704C7, ExCode = 0x40004 HostOSVersion : 10.0.26100 TargetOSVersion : 10.0.26100.3624 (ge_release_svc_prod3.250321-2034) UpgradeStartTime : 14/05/2025 11:24:05 UpgradeEndTime : 14/05/2025 11:24:32 UpgradeElapsedTime : 00:00:27 # Also written to C:\Windows\Logs\SetupDiag\setupdiagresults.xml (1,081 bytes) # The matched rule is documented: "FindAbruptDownlevelFailure — Gives last # operation failure information when the system fails in the downlevel, # but the log just ends abruptly." # # Twenty-seven seconds, start to finish. 0x800704C7 = ERROR_CANCELLED.

Three independent artefacts, in agreement: the registry key, the XML file, and the log line SetupHost: Reporting error event -> [0x800704C7, 0x40004]. All three say 0x800704C7 - 0x40004. And C:\Windows\Logs\Mosetup\BlueBox.log is timestamped 2025-05-14 11:24:44 — the same 27-second window, the documented log for the setup.exe-to-Windows-Update conversation, sitting there ready for the next question.

Gotcha: now decode that extend code with the documented table. 0x40004: first digit 4 is SP_EXECUTION_OOBE_BOOT, last two digits 04 is SP_EXECUTION_OP_INSTALL_RECOVERY_ENVIRONMENT. But SetupDiag matched FindAbruptDownlevelFailure, the log line reads CSetupManager::ExecuteDownlevelMode, the telemetry line reads [Downlevel], and the whole thing lasted 27 seconds — nowhere near OOBE. The table disagrees with four other artefacts. Remember Microsoft's own caveat that those extend codes "apply to Windows 10 version 1607"; this is build 26100. Use the extend code to pick a folder, then let the log text overrule it. Do not open a ticket that says "OOBE phase failure" because a 1607-era table said so.

Case B — the success that contains a textbook failure code

Now the other file, and the reason you must never treat "errors present" as "upgrade failed".

The 63-line setuperr.log in C:\Windows\Panther is from an upgrade that completed successfully. It contains 0x8007042B — the exact result code Microsoft uses in its own worked failure example on the log-files page.

C:\Windows\Panther\setuperr.log — real lines from a SUCCESSFUL upgrade
16:48:49, Error SP Error WRITE, 0x00000005 while gathering/applying object: Registry, HKCU\Software\Zscaler. Will return 0 16:48:49, Error MIG Error 5 while applying object HKCU\Software\Zscaler. Shell application requested abort <-- documented string #1 16:48:49, Error MIG Abandoning apply due to error for object: HKCU\Software\Zscaler <-- documented string #2 16:48:49, Error Apply failed. Last error: 0x00000000 <-- untagged, error = 0 16:48:49, Error SP pSPExecuteApply: Apply operation failed. Error: 0x0000002C 16:48:50, Error SP Apply (machine-specific apply, offline phase): Migration phase failed. Result: 44, no specific error 16:48:50, Error SP Operation failed: Offline portion of machine-specific and machine-independent apply operations. Error: 0x8007042B[gle=0x000000b7] <-- the "fatal" code # 0x8007042B = ERROR_PROCESS_ABORTED. Both of Microsoft's documented # abort strings, one Win32 access-denied on a security agent's HKCU key, # and a migration phase reporting failure. Textbook fatal cluster. # # The upgrade succeeded.

How do I know it succeeded? Because of what happened after that timestamp.

EvidenceTimestampWhat it proves
The 0x8007042B line in setuperr.log16:48:50A migration apply phase failed on one object.
Last line in setuperr.log17:58:12Setup kept logging errors for another 69 minutes after the "fatal" one.
Last line in setupact.log: CBS Ending TrustedInstaller finalization.18:04:20Setup ran 75 minutes past the 0x8007042B and finished cleanly with a CBS finalization, not a rollback.
No $Windows.~BT\Sources\Rollback folder from that dateNo rollback was ever prepared or executed for this upgrade.
Logs present in C:\Windows\PantherThe documented post-upgrade location. Setup only migrates its logs here on completion.
Device now running 25H2, build 26200.9168todayThe upgrade this log describes is the one that put the OS where it is.

Setup hit an access-denied writing a security agent's HKCU key during offline migration, logged it with both of Microsoft's canonical abort strings and a genuinely fatal-looking result code, then carried on and completed. The migration engine is designed to tolerate that. A single object failing to apply is not a failed upgrade.

Which is exactly why the procedure says to find the last occurrence of the result code Setup actually reported — not the last scary line in the file. Without a code from step 2, 0x8007042B at 16:48:50 looks like your answer. With one, you know there is no failure to explain.

Tip: a zero-byte setuperr.log is a result, not an empty file. On my device C:\Windows\Panther\UnattendGC\setuperr.log is 0 bytes — the OOBE phase logged no errors at all. That is one of the fastest facts you can establish in the whole investigation, and it eliminates an entire phase in the time it takes to read a file size. Check the size of every setuperr.log in every phase folder before you open any of them.

The full component histogram of a 63-line file

One last measurement, because it closes the loop on the tag documentation. Here is the complete component breakdown of the successful upgrade's setuperr.log — all 50 timestamped entries.

TagEntriesShareDocumented as useful?
MIG2244%Yes — "migration engine"
SP1530%Yes — "setup platform"
CONX918%Yes — "compatibility information"
MOUPG12%Listed in the nine
DU12%Not in the nine. Documented elsewhere as "DU = Driver/device updates".
untagged24%Summary and [SetupPlatform.exe] lines.

Microsoft says SP, MIG and CONX are the three that matter for troubleshooting Windows Setup errors. On a real device, those three are 46 of 50 entries — 92 percent of the error log. The documentation is not being vague. It is telling you precisely where to look.

The whole thing, as a runbook

  1. Do not retry. Copy C:\$Windows.~BT, C:\Windows\Panther and C:\Windows\Logs\Mosetup somewhere safe first.
  2. Check which phase folders exist. No Rollback folder means it never got that far.
  3. Read HKLM\SYSTEM\Setup\SetupDiag\Results. Setup may have diagnosed it for you already.
  4. If that is empty, look for Application event 1001 named WinSetupDiag02 and read P5 and P6. If the log has rolled, grep setupact.log for Reporting error event.
  5. Use the extend code's first digit to pick the folder — then let the log's own phase text overrule the table.
  6. Get-Item every setuperr.log in every phase folder. Zero bytes eliminates a phase for free.
  7. Read the non-empty setuperr.log end to end. It is measured in tens of lines.
  8. Find the last occurrence of the result code from step 4. Look for Shell application requested abort and Abandoning apply due to error for object.
  9. Decode the Win32 codes with certutil -error. Expect it to fail on 0xC18xxxxx and 0xC19xxxxx; use the documented tables for those.
  10. Take the timestamp into setupact.log and read the Info lines either side. That is where the object, plug-in or hive is named.
  11. Only now widen: miglog.xml for MIG failures, BlueBox.log for payload and WSUS problems, setupapi.dev.log for drivers, CBS.log at the same timestamp for servicing.
  12. Only now decide on a fix.

Twelve steps, and the first ten are read-only. The 547 MB file does not get opened until step 10, and by then you know exactly which second of it you need.

References

All measurements in this article were taken read-only from a live Windows 11 Enterprise 25H2 device, build 26200.9168, on 23 August 2026. No log file was modified, and no repair action was performed. File sizes, line counts, component histograms and registry values were re-measured for this article rather than quoted from memory.

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

More from EndpointWeekly

Windows Update
The folders that look like corruption: Panther, $WINDOWS.~BT and…
A feature update fails and the evidence lands in hidden folders whose names read like…
Windows Update
SetupDiag already named your upgrade failure: reading the report…
Windows Setup runs SetupDiag automatically when an upgrade fails, writing the matched…
Windows Update
0xC1900101 is not one error: the extend code after it names the…
0xC1900101 is a generic rollback code with nine documented causes. The extend code beside…