Exit codes

WinRE Manager returns one of four exit codes. Orchestration should treat them as distinct outcomes, not as success/failure booleans.

The four codes

Code Name Meaning
0 EXIT_SUCCESS WinRE enabled, dedicated recovery partition healthy, state file written or already current.
1 EXIT_REBOOT_REQUIRED Deployment succeeded; a reboot is required to complete WinRE registration.
2 EXIT_WARNING WinRE functional but degraded, or the run deferred work, or a non-fatal failure is queued for retry. Details in the log.
3 EXIT_FATAL Deployment aborted. No state written, or state file deleted. Investigate the log.

Priority

When a run’s outcome satisfies more than one condition, the priority order is:

EXIT_FATAL  >  EXIT_REBOOT_REQUIRED  >  EXIT_WARNING  >  EXIT_SUCCESS

EXIT_FATAL always wins. Between EXIT_REBOOT_REQUIRED and EXIT_WARNING, reboot-required wins — the machine needs to reboot either way.

In practice only two combinations are reachable through the final exit-code determination:

Some exit paths bypass the final determination and exit EXIT_WARNING or EXIT_FATAL directly — the v47 strip-failure abort, the Step 3 → Step 4 pipeline gate, the Audit Mode deferral, the VMD-query-indeterminate deferral, the OS-fallback BitLocker deferral, the v45 pre-shrink deferral (including the v47 race-detector abort reason), the Step 5 race-detector abort, the enable-only target-preparation failure, the enable-failure counter exit, the concurrent-instance deferral, the offline-fallback deferral, the v48 architecture-gate refusal, the v48 elevation-guard refusal, the v48 intervening-anchor surplus rejection, the v48 multi-intervening rejection, the v48 offline LocalInputsId mismatch, and the loop-breaker. Those cases are described in the sections below.

When each code is returned

EXIT_SUCCESS (0)

The fast path found nothing to do and exited cleanly. Or the full-update path completed, WinRE reports Enabled, the state file was written, and no warning flags were set.

Also returned by -DryRun when the dry run completes without errors. Dry runs do not write a state file; they exit 0 from the deployment step.

EXIT_REBOOT_REQUIRED (1)

reagentc /enable returned exit 0 but reagentc /info did not immediately report Enabled. This is a common result after a fresh registration: Windows schedules the registration to complete on the next reboot.

The script writes the state file with PendingReboot = true, records the deployed partition number and disk number so the next run knows where the WIM is, and exits with code 1.

Also returned by the pending-reboot path when the retry reagentc /enable still returns reboot-required, and by the enable-only path when reagentc /enable returns reboot-required.

EXIT_WARNING (2)

Reached when any of the following is true at exit time:

The warning code is returned on the fast path, the enable-only path, the pending-reboot success path, and the full-update path — anywhere a warning flag can be set. In every case the state file is still written (or left in place) if the run reached a state-write point. The v47 strip-failure abort, the Step 3 → Step 4 pipeline gate, the Audit Mode deferral, the VMD-query-indeterminate deferral, the OS-fallback BitLocker deferral, the v45 pre-shrink deferral (including the v47 race-detector reason), the Step 5 race-detector abort, the v44 patch 4 concurrent-instance deferral, and the v44 patch 5 offline-fallback deferral all exit before the state-write point, so any existing state file is left unchanged and no new state is committed. The enable-only failure and the enable-failure counter exit do reach a state-write point and update the state file. The v45 post-delete extension safe fallback reaches the state-write point and writes the state file with the fallback geometry.

Important for orchestration: the table below enumerates sixteen distinct exit-code-2 outcomes, and they require different actions. The bulleted list above this paragraph describes the underlying conditions in more detail; some bullets map to a single table row and a few do not appear as their own row. The state file’s LastUpdated timestamp, the presence of the UsedOSFallback flag, the presence of the deferral marker at C:\Recovery\OEM\winre_partition_deferred.json, and the specific log content distinguish them.

Case State file LastUpdated Log signature Action
OS-fallback Newer than the run start (state file written this run, with UsedOSFallback = true) Dedicated recovery partition creation failed after all attempts. banner The machine ended in OS-fallback. Do not reboot or intervene. Route to a soft-failure queue if your deployment policy requires dedicated partitions.
Strip-failure abort (v47) Unchanged, or state file absent Strip stage failed - candidate rejected. Dismounting with -Discard and deferring before injection, export, partition work, or WinRE disable. The strip stage could not normalize the mounted image to zero third-party drivers. The WIM was not deployed, the partition was not touched, and WinRE was not disabled. The checkpoint was set back to 2, and base.wim and any stale winre_optimized.wim were removed. The next run will retry from step 2 and re-acquire the source. Investigate the specific strip failure reason (enumeration, removal, missing INF field, or budget exhaustion) in the log lines immediately preceding the abort.
Base-WIM copy-integrity check (v47 patch 2) Unchanged, or state file absent Base WIM copy hash mismatch: source=..., copied=... - rejecting candidate or Base WIM copy is unreadable after Copy-Item - rejecting candidate The candidate base.wim did not match the selected source’s SHA256, or the copied file could not be re-read. The candidate is removed, the checkpoint is reset to Step 2, and the run exits EXIT_WARNING. Investigate whether the source changed during acquisition.
Step 3 → Step 4 pipeline gate Unchanged, or state file absent Image injection did not complete. Stopping before Step 4 and before any deployment. The OEM or VMD injection failed after a successful strip. The WIM was not deployed, the partition was not touched, and WinRE was not disabled. The checkpoint was set back to 2. The next run will retry from step 2. Investigate the injection failure reason (OEM pack download, extraction, INF validation, or VMD driver download).
Audit Mode deferral Unchanged, or state file absent Deferring WinRE Manager: Windows is not in a normal-running state (Setup\State\ImageState=…) The machine has not finished OOBE, or is in Audit Mode or a sysprep phase. No partition work was attempted. Complete OOBE, sign in to a normal desktop session, and re-run. Do not retry immediately.
VMD query indeterminate (v44 patch 6) Unchanged, or state file absent VMD hardware detection reported N error(s) during PnP enumeration: … followed by VMD hardware detection was indeterminate; deferring because the driver set cannot be safely determined. A PnP enumeration error prevented the VMD hardware presence check from completing. The correct driver set cannot be determined, so the run defers rather than guessing. No WIM was deployed, no partition was touched, no reagentc call was made. Resolve the PnP service issue (Windows device management, an antivirus/EDR product blocking device enumeration, a device in an error state) and re-run.
OS-fallback BitLocker deferral Unchanged, or state file absent OS-fallback deferred: C: could not be confirmed fully decrypted (Test-VolumeEncrypted=…) followed by the operator guidance line The dedicated partition could not be created and the OS-fallback target (C:) is not confirmed fully decrypted. No WIM was deployed, no reagentc call was made. Wait for C: to reach FullyDecrypted (or complete decryption of C: with manage-bde -off C:), then re-run. Do not retry immediately — the same gate will fire.
Pre-shrink deferral (v45 patch 1; v46 patch 2 added reasons; v47 added the race-detector reason) Unchanged, or state file absent Dedicated replacement deferred before partition deletion (<Reason>). The existing WinRE route was preserved; not attempting OS-fallback. The destructive replacement was deferred before any partition was deleted. The old recovery partition is still present and WinRE is still registered to it; as of v48 patch 1, all deferral reasons leave the machine with WinRE still Enabled (the pre-deletion resolver guard was moved ahead of the pre-shrink and ahead of /disable). The <Reason> names the specific constraint. If the reason is registered source changed before disable, the abort was the v47 race detector catching a Windows Update servicing event during candidate preparation; simply re-run — the source is now stable, and the next run will re-select the source and prepare a fresh candidate. If the reason is any other, free space on C:, defragment, correct the disk layout, or address the oversized partition. After resolving, delete C:\Recovery\OEM\winre_partition_deferred.json (and, if you also want to clear the deployment identity, C:\Recovery\OEM\winre_state.json) to force a retry. See troubleshooting.md for the reason-specific resolutions.
Registered-source fingerprint abort at Step 5 (v47) Unchanged, or state file absent Registered WinRE source changed during candidate preparation - aborting before /disable. The old WinRE route remains intact; no partition changes have been made at this site. The v47 race detector caught a Windows Update servicing event during candidate preparation, at the Step 5 /disable site. WinRE is still Enabled, no partition was touched, no WIM was deployed. The checkpoint was set back to 2, and base.wim and any stale winre_optimized.wim were removed. Simply re-run — the next run will re-select the source and prepare a fresh candidate based on the newly-registered image. This is not a failure; it is the design’s intended response to a source that changed mid-preparation.
Enable-only failure (counter < 3) Newer than the run start (state file written this run, with LastEnableResult set to "failed" or "bitlocker" and the counter incremented) One of: Enable-only /enable failed (attempt N of 3).; Enable-only /enable refused with the BitLocker error after the target partition was confirmed unencrypted (attempt N of 3).; Enable-only path: target recovery partition could not be made unencrypted - deferring without further changes (target-preparation failure). The deployment is current; only the enable step failed. Do not rebuild. Investigate the enable failure itself (ReAgent.xml corruption, missing registration, a Windows component problem, an antivirus product holding the recovery partition open). The next run will retry enable-only. After three consecutive failures the loop-breaker fires and the next run exits with code 3.
Concurrent-instance deferral (v44 patch 4) Unchanged, or state file absent Another WinRE Manager instance is already running (program lock file is exclusively held). Not a failure. The other instance is doing the work and will complete on its own. Do not investigate the log for a deployment problem, do not retry, do not intervene. If your orchestration treats exit 2 as a soft failure and re-queues the remediation, be aware that the re-queue will also exit 2 until the first instance completes. Either wait, or disable the scheduled task before running a manual remediation. See deployment.md.
Offline-fallback deferral (v44 patch 5) Unchanged, or state file absent Offline fallback: the machine requires a full update (state file is stale or unhealthy), but the driver manifest is unavailable. The network was unavailable and the state file indicates a full update is needed. No operator action is required — the next scheduled run with network will complete the work. If the machine will be offline for a prolonged period and the deployment is stale, resolve the network issue or wait. If the log instead shows Offline fallback: using state file's stored DesiredStateId …, the fast path fired successfully and the exit is a degraded-success, not a deferral — the machine is healthy and unchanged. Do not treat it as a failure.
Architecture-gate refusal (v48 patch 1) Unchanged, or state file absent Unsupported OS architecture '<arch>': this manager supports x64 only. The startup architecture check refused. Expected on ARM64, x86, or machines whose architecture could not be resolved. No state was committed. This is a stable deferral: any machine whose architecture is not x64 will continue to exit 2 on every run until the manager adds support or the machine is replaced. Do not retry expecting a different result.
Intervening-anchor surplus rejection (v48 patch 1) Unchanged, or state file absent intervening anchor is N MiB smaller than the plan requires to seat the recovery partition at the disk tail; this v48 scope does not extend the anchor (BitLocker). The intervening-anchor layout (C: \| D: \| Recovery) had a surplus: the recovery partition being reclaimed is larger than the new bucket size, so the plan cannot seat the new recovery partition at the disk tail without extending the anchor. The v48 scope does not extend the anchor (BitLocker-encrypted anchors are not safely growable via Resize-Partition alone). The old recovery partition is intact; no partition was touched. Operator action: extend the anchor to close the gap, or reduce the desired recovery partition size, then delete C:\Recovery\OEM\winre_state.json and C:\Recovery\OEM\winre_partition_deferred.json to force a retry.
Multi-intervening rejection (v48 patch 1) Unchanged, or state file absent recovery-typed partitions exist beyond the intervening anchor's recovery cluster; this layout is not supported The layout has two or more non-recovery partitions between C: and the type-coded recovery cluster (C: \| D: \| E: \| Recovery). The v48 scope is deliberately narrow: exactly one intervening partition, no partition-moving. Same stable deferral as v47, but the v48 message names the intervening partitions via Format-PartitionRef. Automating multi-intervening handling is a v49 candidate.
Offline LocalInputsId mismatch (v48 patch 1) Unchanged, or state file absent Offline fallback: stored LocalInputsId <hash> does not match the current locally-computable inputs <hash>. The machine was offline and the state file’s stored LocalInputsId did not match the current machine’s locally-computable inputs (hardware identity, OS build, CPU vendor/generation). A hardware or OS input changed while the machine was offline; the stored DesiredStateId no longer describes this machine. The machine is unchanged. Operator action: bring the machine online so a fresh manifest can be fetched and a new DesiredStateId computed; the next scheduled run will do this automatically.

The distinguishing factor between OS-fallback and the deferral/gate cases is the state file timestamp: OS-fallback reaches the state-write step and updates LastUpdated; the v47 strip-failure abort, the Step 3 → Step 4 pipeline gate, the Audit Mode deferral, the VMD-query-indeterminate deferral, the OS-fallback BitLocker deferral, the v45 pre-shrink deferral (including the v47 race-detector reason), the v47 Step 5 race-detector abort, the concurrent-instance deferral, and the offline-fallback deferral all exit before it and leave the timestamp unchanged. The enable-only failure also updates the state file, but its log signature is unique and cannot be confused with OS-fallback.

A partition-creation failure — with its Dedicated recovery partition creation failed after all attempts. banner — is only logged when the destructive attempt actually ran and failed. A deferral or a pipeline gate is not that.

EXIT_FATAL (3)

Reached when any of the following occurs:

Fatal exits do not write a state file. If a state file was written earlier in the run and the fatal exit occurs after that point, the state file is left as-is; on the next run, the fast path may fire if the state is now healthy, or the full-update path may re-run if it is not.

Special case for orchestration: exit code 3 with the log line FATAL: WinRE is not enabled at exit on a machine that no longer has a recovery partition indicates the pre-patch-5 failure mode. Do not retry automatically. Follow the recovery procedure in troubleshooting.md.

Second special case: exit code 3 with the log line Refusing to retry reagentc /enable indicates the enable-failure loop-breaker. Do not retry automatically — the same guard will fire on the next run because the state file still records the counter value. Resolve the underlying cause, delete the state file, and re-run. See troubleshooting.md for the diagnosis procedure.

What the codes do not tell you

For any of those details, read the log. See troubleshooting.md.

Exit codes on the pending-reboot path

The pending-reboot path has its own exit logic. In order:

  1. Check the repair-attempt count first. The state file’s RepairAttempts is incremented before any other work. If the incremented value exceeds 3 (equivalently, the state file already records RepairAttempts >= 3), the run exits EXIT_FATAL immediately without attempting repair. This guard is a precondition on the whole pending-reboot path, not a post-condition on its outcome.
  2. Resolve the deployed target from the state file (DeployedDiskNumber / DeployedPartitionNumber, or C:\Recovery\WindowsRE for OS-fallback).
  3. Prepare the target:
  4. Re-run reagentc /enable against the recorded path. If the retry succeeded and WinRE reports Enabled:
  5. If the retry still reports reboot-required → EXIT_REBOOT_REQUIRED.

Note that PendingReboot and RepairAttempts are recorded in the state file before the exit, so a machine that exits with code 3 due to too many repair attempts still has a state file reflecting the current repair count.

The pending-reboot path writes the state file with LastEnableResult = "ok" and EnableFailureAttempts = 0. A machine that reaches the pending-reboot path therefore has its enable-failure counter reset regardless of the outcome — the pending-reboot path represents a different failure mode (registration did not complete after a reboot) and is tracked by the separate RepairAttempts counter. The two counters are independent. A target-preparation failure on the pending-reboot path does not increment EnableFailureAttempts; the exclusion is deliberate, because immediately after a reboot the target partition’s encryption state may be transiently indeterminate, and the pending-reboot path is tracked exclusively by RepairAttempts.

Exit codes and orchestration

Recommended orchestration policy:

Code Action
0 Record success. No further action.
1 Schedule a reboot at the next maintenance window. The next run will finish the registration.
2 Investigate the log. Check the state file’s LastUpdated timestamp, the UsedOSFallback flag, and whether a deferral marker exists at C:\Recovery\OEM\winre_partition_deferred.json. Sixteen cases: (a) If the log shows the Dedicated recovery partition creation failed after all attempts. banner and the state file was updated this run with UsedOSFallback = true, the machine ended up in OS-fallback. Do not reboot or intervene while encryption is in progress. (b) If the log shows Strip stage failed - candidate rejected. Dismounting with -Discard and deferring before injection, export, partition work, or WinRE disable. and the state file was not updated, the v47 strip stage could not normalize the mounted image. No WIM was deployed, no partition touched, WinRE not disabled. The checkpoint was reset to 2. Investigate the specific strip failure reason in the log lines immediately preceding the abort (enumeration, removal, missing INF field, or budget exhaustion). The next run will retry from step 2 and re-acquire the source. (c) If the log shows Image injection did not complete. Stopping before Step 4 and before any deployment. and the state file was not updated, OEM or VMD injection failed after a successful strip. Same remediation as the pre-v47 case: no WIM was deployed, no partition touched, WinRE not disabled. The checkpoint was reset to 2. Investigate the injection failure reason. (d) If the log shows Deferring WinRE Manager: Windows is not in a normal-running state (Setup\State\ImageState=…) and the state file was not updated, the machine has not finished OOBE or is in Audit Mode. Complete OOBE and re-run. (e) If the log shows VMD hardware detection was indeterminate; deferring because the driver set cannot be safely determined. and the state file was not updated, a PnP enumeration error prevented the VMD hardware presence check from completing. Resolve the PnP service issue (Windows device management, an antivirus/EDR product blocking device enumeration, a device in an error state) and re-run. (f) If the log shows OS-fallback deferred: C: could not be confirmed fully decrypted (Test-VolumeEncrypted=…) and the state file was not updated, the dedicated partition could not be created and the OS-fallback target is not confirmed fully decrypted. Wait for C: to reach FullyDecrypted or complete decryption of C: (manage-bde -off C:), then re-run. (g) If the log shows Dedicated replacement deferred before partition deletion (<Reason>). and the state file was not updated, the v45 pre-shrink deferral fired (v46 patch 2 added two reasons; v47 added registered source changed before disable). The old recovery partition is still present. If the reason is registered source changed before disable, simply re-run — the v47 race detector caught a Windows Update servicing event during candidate preparation; the source is now stable and the next run will re-select and prepare a fresh candidate. For any other reason, resolve the constraint (free space on C:, correct the disk layout, address the oversized partition, retry the transient read failure, resolve the active-route resolution failure, or investigate the shrink or route-restore failure), then delete C:\Recovery\OEM\winre_partition_deferred.json and, if you also want to clear the deployment identity, C:\Recovery\OEM\winre_state.json to force a retry. If the reason is active WinRE location could not be resolved, note that as of v48 patch 1 the guard fires ahead of the pre-shrink and ahead of reagentc /disable, so the machine is left with WinRE still Enabled — see troubleshooting.md for the re-registration procedure. (h) If the log shows Registered WinRE source changed during candidate preparation - aborting before /disable. The old WinRE route remains intact; no partition changes have been made at this site. and the state file was not updated, the v47 race detector fired at the Step 5 /disable site. WinRE is still Enabled, no partition touched, no WIM deployed. The checkpoint was reset to 2 and base.wim and any stale winre_optimized.wim were removed. Simply re-run — this is the design’s intended response to a source that changed mid-preparation, not a failure. (i) If the log shows Enable-only /enable failed (attempt N of 3) or Enable-only /enable refused with the BitLocker error after the target partition was confirmed unencrypted (attempt N of 3) and the state file was updated with a non-"ok" LastEnableResult, the deployment is current and only the enable step failed. Investigate the enable failure itself; the next run retries enable-only. After three consecutive failures the loop-breaker fires (exit code 3). (j) If the log shows Another WinRE Manager instance is already running (program lock file is exclusively held), a concurrent instance was running. This is not a failure — the other instance is doing the work. Do not investigate; wait for the other instance to complete, then re-check. If your orchestration re-queues soft failures, be aware that the re-queue may also exit 2 until the first instance releases the lock. (k) If the log shows Offline fallback: the machine requires a full update (state file is stale or unhealthy), but the driver manifest is unavailable, the network was unavailable and the state file indicates a full update is needed. No operator action is required — the next scheduled run with network will complete the work. If the log instead shows Offline fallback: using state file's stored DesiredStateId …, the fast path fired successfully and this is a degraded-success, not a deferral. (l) If the log shows Unsupported OS architecture '<arch>' and the state file was not updated, the v48 architecture gate refused. This is a stable deferral: any machine whose architecture is not x64 will continue to exit 2 on every run until the manager adds support or the machine is replaced. (m) If the log shows intervening anchor is N MiB smaller than the plan requires to seat the recovery partition at the disk tail and the state file was not updated, the v48 surplus rejection fired. The old recovery partition is intact; no partition was touched. Extend the anchor, or reduce the desired recovery partition size, then delete the state file and deferral marker to force a retry. (n) If the log shows recovery-typed partitions exist beyond the intervening anchor's recovery cluster; this layout is not supported and the state file was not updated, the v48 multi-intervening rejection fired. Same stable deferral as v47. (o) If the log shows Offline fallback: stored LocalInputsId <hash> does not match the current locally-computable inputs <hash> and the state file was not updated, the v48 offline hardware-drift guard fired. The machine is unchanged; the next run with network recomputes the DSI and either converges or defers normally. (p) If the log shows Base WIM copy hash mismatch: source=..., copied=... - rejecting candidate or Base WIM copy is unreadable after Copy-Item - rejecting candidate, the v47 patch 2 base-WIM copy-integrity check rejected the candidate. The candidate base.wim was removed, the checkpoint was reset to Step 2, and the run exited EXIT_WARNING. Investigate whether the source changed during acquisition. Cases (b), (c), (d), (e), (f), (g), (h), (j), (k), (l), (m), (n), (o), and (p) leave the machine unchanged. Cases (a) and (i) update the state file.
3 Do not retry automatically. Investigate the log immediately. If the log shows FATAL: WinRE is not enabled at exit on a machine that no longer has a recovery partition, follow the troubleshooting.md recovery procedure before retrying. If the log shows Refusing to retry reagentc /enable, resolve the enable failure, delete the state file, then re-run. If the log shows Driver manifest unavailable and no state file exists, the machine has no state file and no network; retry when the network is available. If the log shows Cannot rename because item at '<workspace>\winre.wim' does not exist and an earlier line shows Could not set up program lock at …, investigate why the lock could not be acquired (permissions on C:\ProgramData\OEM\Logs\, a missing directory, a transient filesystem issue); the run proceeded unprotected and collided with another instance.

Do not use exit code 0 as the sole health signal. A machine that reached OS-fallback exits with 2, which is a legitimate “the machine is functional but the design goal was not achieved” signal. If your deployment policy requires dedicated recovery partitions, treat 2 as a soft failure and route it to a queue.

Do not configure retry loops that ignore the exit code and re-run unconditionally. None of the deferral states is made better by retrying — the same gate will fire on the next run. Wait until the underlying condition resolves (manage-bde -status C: reads a safe state on the OS-fallback route, the PnP enumeration error clears, the machine has finished OOBE, the pre-shrink constraint is freed, or the marker is cleared), then re-run. Two v47-specific retry exceptions:

For the enable-failure counter, do not retry blindly: the counter is designed to break a silent loop, and after three consecutive failures the loop-breaker fires and requires manual intervention. Investigate the enable failure itself rather than cycling the script. For the concurrent-instance deferral, the correct action is to wait; the other instance is already doing the work.