Epic Games Launcher stuck on Resume after UE 5.8.x update – manifest commit never completes [Workaround v2]

Update – October 2026

The workaround has now been independently confirmed by another user.

They first tried a full uninstall/reinstall of UE 5.8, but the issue remained unchanged.

After that, they used the PowerShell v2.0 workaround from this thread and confirmed that it solved the problem:

“The uninstall/reinstall didn’t help at all. I ended up using your PowerShell script which solved the issue. Many thanks!”

This is important because it independently confirms that:

  • reinstalling the Engine does not necessarily fix the problem
  • the physical Engine installation itself is not necessarily corrupted
  • the issue is consistent with a stale/incomplete Launcher manifest state
  • the v2.0 workaround can restore the Launcher to the correct installed state

At this point, the v2.0 workaround has been successfully validated on:

  • my reproduced UE 5.8.1 → 5.8.2 failure
  • my reproduced UE 5.8.2 → 5.8.3 failure
  • an independent UE 5.8.x affected installation reported by another user

The Epic ticket UE-398557 was later closed as a duplicate of an existing known issue.

The parent/original issue ID has not yet been publicly identified in this thread.

Recommended action: before reinstalling UE 5.8, use the Workaround v2.0 below.

It runs in read-only DRY-RUN mode by default and can confirm whether your installation matches the same manifest-commit issue before making any changes.

Update – September 2026

This issue has now been reproduced on both UE 5.8.1 → 5.8.2 and UE 5.8.2 → 5.8.3.

Epic has opened UE-398557, currently marked Ready for QA.

I also added a generic PowerShell diagnostic/workaround v2.0 below. It automatically detects the affected UE 5.8.x target version from the Pending transaction and runs in read-only DRY-RUN mode by default.

Use v2.0 instead of the older 5.8.2-specific workaround.

Summary

Epic Games Launcher gets stuck in a Resume loop after updating Unreal Engine 5.8.1 to 5.8.2.

The engine files are successfully updated to UE 5.8.2 / CL 56702186, and BuildPatch reports ProcessSuccess=TRUE / ErrorCode=OK. However, the Launcher fails to commit the final installed manifest and returns to Resume without downloading anything.

The Launcher log shows:
IncompleteInstall=1 AutoResume=1
followed by:
completed, waiting for manifest commit before starting next download

There is also a suspicious MainGameAppId mismatch where the valid on-disk AppId is reconciled against catalog=(null):(null):(null).

What Type of Bug are you experiencing?

Other

Steps to Reproduce

  1. Have Unreal Engine 5.8.1 installed through Epic Games Launcher.
  2. Start the update to Unreal Engine 5.8.2.
  3. Allow the update to finish.
  4. Observe that Epic Games Launcher changes the engine state to “Resume”.
  5. Click Resume/Update again.
  6. The operation runs for only a few seconds, downloads no additional engine data, and returns to “Resume”.
  7. Check UnrealEditor.exe properties or Engine/Build/Build.version:
    • File version: 5.8.2.0
    • Product version: ++UE5+Release-5.8-CL-56702186
  8. Check the Launcher log. BuildPatch reports success, but the installation remains marked as incomplete and waits for a manifest commit.

Expected Result

After BuildPatch successfully completes the UE 5.8.2 update, Epic Games Launcher should commit the new installed manifest, clear the incomplete-install state, and display Unreal Engine 5.8.2 with the Launch button.

Observed Result

The Unreal Engine files are already UE 5.8.2 / CL 56702186, but Epic Games Launcher continues to report the previous 5.8.1 installation state and shows Resume.

Repeated Resume/Update attempts do not download additional data.

The log reports a successful BuildPatch operation, followed by:

IncompleteInstall=1 AutoResume=1

and:

completed, waiting for manifest commit before starting next download

The manifest commit does not complete.

A related warning appears immediately before this:

MainGameAppId mismatch detected for app UE_5.8
on-disk=ue:18b3b415bc434c5b974f50488360ca31:UE_5.8
catalog=(null):(null):(null)
Correcting to catalog value.

Affects Versions

5.8

Platform(s)

Windows

Upload an image

!

Additional Notes

Additional diagnostics:

The physical Unreal Engine installation was already fully updated to UE 5.8.2 / CL 56702186 before the Launcher UI was fixed.

The main UE 5.8 manifest matched the 5.8.2 build, and BuildPatch completed with:
ProcessSuccess: TRUE
ErrorCode: OK
FailureReasonText: The operation was successful.

The issue was isolated to the Launcher metadata/final manifest commit stage.

For diagnostic purposes, after backing up the original metadata and with Epic Games Launcher completely closed, I manually reconciled the installed UE_5.8 metadata to the already-installed 5.8.2 manifest and removed only the stale UE 5.8 pending transaction files.

After restarting Epic Games Launcher, it immediately displayed:
Unreal Engine 5.8.2
Launch

No additional Engine files had to be downloaded.

I have preserved the original installed .item, pending .item, manifests and Launcher logs if Epic needs them for investigation.

1 Like

Update: confirmed workaround + safe PowerShell diagnostic

Another user has now reported what appears to be the same UE 5.8.1 → 5.8.2 Launcher issue, so I am adding the diagnostic/workaround I used to recover my installation.

Important clarification

In my case, the very first UE 5.8.1 → 5.8.2 Update attempt had already updated the actual Engine files successfully.

After that first Update:

UnrealEditor.exe
Numeric FileVersion: 5.8.2.0
ProductVersion: ++UE5+Release-5.8-CL-56702186

Engine\Build\Build.version
Version: 5.8.2
Changelist: 56702186

However, Epic Games Launcher still displayed:

5.8.1
Resume

Clicking Resume/Update again downloaded no meaningful Engine data and returned to Resume.

The Launcher log showed that BuildPatch itself completed successfully:

ProcessSuccess: TRUE
ErrorCode: OK
FailureReasonText: The operation was successful.

but afterwards remained at:

IncompleteInstall=1 AutoResume=1
completed, waiting for manifest commit before starting next download

Therefore this workaround is not intended to force-install UE 5.8.2. It only attempts to reconcile the Launcher metadata when the actual Engine has already been successfully updated to 5.8.2 / CL 56702186.


PowerShell diagnostic / workaround

The script is deliberately READ-ONLY by default:

$ApplyChanges = $false

In this mode it:

  • locates the installed UE_5.8 Launcher metadata automatically,
  • verifies UnrealEditor.exe,
  • verifies Engine\Build\Build.version,
  • verifies the installed manifest,
  • checks LauncherInstalled.dat,
  • detects the active UE 5.8 pending transaction,
  • validates the pending UE 5.8.2 metadata,
  • simulates the final metadata commit in memory only.

It does not modify, copy or delete anything.

If the system is already fixed, the script exits with:

STATUS: ALREADY HEALTHY
UE 5.8.2 metadata is already committed.
No active UE 5.8 Pending transaction exists.
No changes were made.

I tested this state after recovering my installation and the script correctly detected the healthy UE 5.8.2 installation.

If the problem is present, the expected diagnostic result is:

STATUS: AFFECTED / CONDITIONS MATCH

Physical Engine:
  UE 5.8.2 / CL 56702186

Installed metadata:
  5.8.1-56057345+++UE5+Release-5.8-Windows

Pending target:
  5.8.2-56702186+++UE5+Release-5.8-Windows

In-memory commit simulation:
  PASSED

DRY RUN PASSED
No files were modified, copied or deleted.

Only after DRY RUN PASSED, the same script can be changed to:

$ApplyChanges = $true

The Apply mode creates a complete backup before changing anything, then asks the user to completely exit Epic Games Launcher and explicitly type:

APPLY

before performing the metadata reconciliation.

The backup contains the installed .item, Pending .item, installed manifest, Pending manifest, LauncherInstalled.dat and Build.version.

The script removes only the UE 5.8-specific pending transaction and does not remove the entire Pending directory.

In my case, after the workaround and restarting Epic Games Launcher, it immediately displayed:

Unreal Engine 5.8.2
Launch

No additional Engine download was required.

Warning

This is an unofficial workaround, not an Epic fix.

Do not use Apply mode unless the DRY-RUN confirms that the physical Engine is already exactly UE 5.8.2 / CL 56702186 and the remaining problem is the Launcher metadata/pending transaction.

Keep the automatically-created backup until Epic provides an official fix.

:warning: Deprecated – use v2.0 instead

This older workaround is specific to UE 5.8.2 and has been superseded by the generic UE 5.8.x PowerShell diagnostic/workaround v2.0.

Please use v2.0 for UE 5.8.2, 5.8.3 and later 5.8.x hotfixes.

Tip: The copy button for the full script is in the top-right corner of the code block.

& {
    $ErrorActionPreference = "Stop"
    Set-StrictMode -Version Latest


    # ============================================================
    # MODE
    # ============================================================
    #
    # DEFAULT = SAFE / READ-ONLY
    #
    # Leave this as $false first.
    #
    # Change to $true ONLY after DRY RUN PASSED and only if the
    # system matches the issue described in this thread.
    #
    # ============================================================

    $ApplyChanges = $false


    # ============================================================
    # EXPECTED UE BUILD
    # ============================================================

    $ExpectedAppVersion =
        "5.8.2-56702186+++UE5+Release-5.8-Windows"

    $PreviousAppVersion =
        "5.8.1-56057345+++UE5+Release-5.8-Windows"

    $ExpectedMajor = 5
    $ExpectedMinor = 8
    $ExpectedPatch = 2
    $ExpectedCL    = 56702186


    # ============================================================
    # LAUNCHER PATHS
    # ============================================================

    $ManifestRoot =
        "C:\ProgramData\Epic\EpicGamesLauncher\Data\Manifests"

    $PendingRoot =
        Join-Path $ManifestRoot "Pending"

    $LauncherDat =
        "C:\ProgramData\Epic\UnrealEngineLauncher\LauncherInstalled.dat"


    # ============================================================
    # HELPER
    # ============================================================

    function Read-JsonFile {
        param(
            [Parameter(Mandatory = $true)]
            [string]$Path
        )

        Get-Content -LiteralPath $Path -Raw |
            ConvertFrom-Json
    }


    Write-Host ""
    Write-Host "==========================================="
    Write-Host " UE 5.8.2 LAUNCHER MANIFEST DIAGNOSTIC"
    Write-Host "==========================================="

    if ($ApplyChanges) {
        Write-Host "MODE: APPLY CHANGES"
    }
    else {
        Write-Host "MODE: DRY RUN / READ-ONLY"
    }


    # ============================================================
    # 1. FIND INSTALLED UE_5.8 ITEM
    # ============================================================

    if (-not (Test-Path $ManifestRoot)) {
        throw "STOP: Epic Games Launcher manifest directory was not found."
    }

    $MainCandidates = @(
        Get-ChildItem `
            -LiteralPath $ManifestRoot `
            -Filter "*.item" `
            -File |
        ForEach-Object {

            try {
                $J = Read-JsonFile $_.FullName

                if ($J.AppName -eq "UE_5.8") {
                    [PSCustomObject]@{
                        Path = $_.FullName
                        Data = $J
                    }
                }
            }
            catch {
                # Ignore unrelated/unreadable item files.
            }
        }
    )

    if ($MainCandidates.Count -ne 1) {
        throw "STOP: Expected exactly one installed UE_5.8 item, found $($MainCandidates.Count)."
    }

    $MainItemPath =
        $MainCandidates[0].Path

    $Main =
        $MainCandidates[0].Data

    Write-Host ""
    Write-Host "[1] Installed UE_5.8 metadata"
    Write-Host "Item       : $MainItemPath"
    Write-Host "Version    : $($Main.AppVersionString)"
    Write-Host "Incomplete : $($Main.bIsIncompleteInstall)"
    Write-Host "Location   : $($Main.InstallLocation)"


    # ============================================================
    # 2. VERIFY PHYSICAL UNREAL ENGINE
    # ============================================================

    if ([string]::IsNullOrWhiteSpace($Main.InstallLocation)) {
        throw "STOP: UE_5.8 InstallLocation is empty."
    }

    $EditorExe =
        Join-Path `
            $Main.InstallLocation `
            "Engine\Binaries\Win64\UnrealEditor.exe"

    if (-not (Test-Path $EditorExe)) {
        throw "STOP: UnrealEditor.exe was not found."
    }

    $VI =
        (Get-Item $EditorExe).VersionInfo

    $NumericFileVersion =
        "{0}.{1}.{2}.{3}" -f `
            $VI.FileMajorPart,
            $VI.FileMinorPart,
            $VI.FileBuildPart,
            $VI.FilePrivatePart

    Write-Host ""
    Write-Host "[2] Physical UnrealEditor.exe"
    Write-Host "Numeric FileVersion : $NumericFileVersion"
    Write-Host "FileVersion string  : $($VI.FileVersion)"
    Write-Host "ProductVersion      : $($VI.ProductVersion)"

    if (
        $VI.FileMajorPart -ne $ExpectedMajor -or
        $VI.FileMinorPart -ne $ExpectedMinor -or
        $VI.FileBuildPart -ne $ExpectedPatch
    ) {
        throw "STOP: UnrealEditor.exe is not UE 5.8.2."
    }

    if ($VI.ProductVersion -notlike "*CL-$ExpectedCL*") {
        throw "STOP: UnrealEditor.exe is not CL $ExpectedCL."
    }


    # ============================================================
    # 3. VERIFY Engine\Build\Build.version
    # ============================================================

    $BuildVersionPath =
        Join-Path `
            $Main.InstallLocation `
            "Engine\Build\Build.version"

    if (-not (Test-Path $BuildVersionPath)) {
        throw "STOP: Engine\Build\Build.version was not found."
    }

    $Build =
        Read-JsonFile $BuildVersionPath

    Write-Host ""
    Write-Host "[3] Engine Build.version"
    Write-Host "Version    : $($Build.MajorVersion).$($Build.MinorVersion).$($Build.PatchVersion)"
    Write-Host "Changelist : $($Build.Changelist)"

    if (
        $Build.MajorVersion -ne $ExpectedMajor -or
        $Build.MinorVersion -ne $ExpectedMinor -or
        $Build.PatchVersion -ne $ExpectedPatch -or
        $Build.Changelist -ne $ExpectedCL
    ) {
        throw "STOP: Build.version does not report UE 5.8.2 / CL $ExpectedCL."
    }


    # ============================================================
    # 4. VERIFY INSTALLED MANIFEST
    # ============================================================

    if ([string]::IsNullOrWhiteSpace($Main.CompleteManifestPath)) {
        throw "STOP: CompleteManifestPath is empty."
    }

    if (-not (Test-Path $Main.CompleteManifestPath)) {
        throw "STOP: Installed manifest does not exist: $($Main.CompleteManifestPath)"
    }

    $InstalledManifestHash =
        (Get-FileHash `
            $Main.CompleteManifestPath `
            -Algorithm SHA256).Hash

    Write-Host ""
    Write-Host "[4] Installed manifest"
    Write-Host "Path   : $($Main.CompleteManifestPath)"
    Write-Host "SHA256 : $InstalledManifestHash"


    # ============================================================
    # 5. READ LauncherInstalled.dat
    # ============================================================

    if (-not (Test-Path $LauncherDat)) {
        throw "STOP: LauncherInstalled.dat was not found."
    }

    $Launcher =
        Read-JsonFile $LauncherDat

    $UE58Entries = @(
        $Launcher.InstallationList |
        Where-Object {
            $_.AppName -eq "UE_5.8"
        }
    )

    if ($UE58Entries.Count -ne 1) {
        throw "STOP: Expected exactly one UE_5.8 entry in LauncherInstalled.dat."
    }

    $UE58 =
        $UE58Entries[0]

    Write-Host ""
    Write-Host "[5] LauncherInstalled.dat"
    Write-Host "AppName    : $($UE58.AppName)"
    Write-Host "AppVersion : $($UE58.AppVersion)"


    # ============================================================
    # 6. FIND ACTIVE UE_5.8 PENDING TRANSACTION
    # ============================================================

    $PendingCandidates = @()

    if (Test-Path $PendingRoot) {

        $PendingCandidates = @(
            Get-ChildItem `
                -LiteralPath $PendingRoot `
                -Filter "*.item" `
                -File `
                -ErrorAction SilentlyContinue |
            ForEach-Object {

                try {
                    $J = Read-JsonFile $_.FullName

                    if ($J.AppName -eq "UE_5.8") {
                        [PSCustomObject]@{
                            Path = $_.FullName
                            Data = $J
                        }
                    }
                }
                catch {
                    # Ignore unrelated/unreadable Pending items.
                }
            }
        )
    }


    # ============================================================
    # ALREADY HEALTHY?
    # ============================================================

    if ($PendingCandidates.Count -eq 0) {

        if (
            $Main.AppVersionString -eq $ExpectedAppVersion -and
            $Main.bIsIncompleteInstall -eq $false -and
            $UE58.AppVersion -eq $ExpectedAppVersion
        ) {

            Write-Host ""
            Write-Host "==========================================="
            Write-Host " STATUS: ALREADY HEALTHY"
            Write-Host "==========================================="
            Write-Host "UE 5.8.2 metadata is already committed."
            Write-Host "No active UE 5.8 Pending transaction exists."
            Write-Host "No changes were made."
            Write-Host "==========================================="

            return
        }

        Write-Host ""
        Write-Host "==========================================="
        Write-Host " STATUS: PENDING TRANSACTION NOT FOUND"
        Write-Host "==========================================="
        Write-Host ""
        Write-Host "The physical Engine is UE 5.8.2, but no active"
        Write-Host "UE_5.8 Pending transaction was found."
        Write-Host ""
        Write-Host "If Epic Games Launcher is stuck on Update/Resume:"
        Write-Host ""
        Write-Host "1. Open Epic Games Launcher."
        Write-Host "2. Click Update/Resume once."
        Write-Host "3. Wait until it returns to Resume."
        Write-Host "4. Run this script again BEFORE closing Launcher."
        Write-Host ""
        Write-Host "No changes were made."
        Write-Host "==========================================="

        return
    }


    if ($PendingCandidates.Count -ne 1) {
        throw "STOP: More than one UE_5.8 Pending item was found."
    }

    $PendingItemPath =
        $PendingCandidates[0].Path

    $Pending =
        $PendingCandidates[0].Data

    Write-Host ""
    Write-Host "[6] Active Pending transaction"
    Write-Host "Item       : $PendingItemPath"
    Write-Host "Version    : $($Pending.AppVersionString)"
    Write-Host "Incomplete : $($Pending.bIsIncompleteInstall)"
    Write-Host "PrereqSHA1 : $($Pending.PrereqSHA1Hash)"


    # ============================================================
    # 7. VALIDATE PENDING METADATA
    # ============================================================

    if ($Pending.AppVersionString -ne $ExpectedAppVersion) {
        throw "STOP: Pending transaction is not UE 5.8.2 / CL $ExpectedCL."
    }

    if ($Pending.bIsIncompleteInstall -ne $true) {
        throw "STOP: Pending UE_5.8 item is not marked as incomplete."
    }

    if (
        [string]::IsNullOrWhiteSpace($Pending.PrereqSHA1Hash) -or
        $Pending.PrereqSHA1Hash -notmatch '^[0-9A-Fa-f]{40}$'
    ) {
        throw "STOP: Pending PrereqSHA1Hash is invalid."
    }

    if (
        -not [string]::IsNullOrWhiteSpace($Pending.InstallLocation) -and
        $Pending.InstallLocation -ne $Main.InstallLocation
    ) {
        throw "STOP: Pending InstallLocation does not match installed UE_5.8."
    }


    # ============================================================
    # 8. LOCATE PENDING MANIFEST
    # ============================================================

    if ([string]::IsNullOrWhiteSpace($Main.PendingManifestPath)) {
        throw "STOP: Installed UE_5.8 item has no PendingManifestPath."
    }

    $PendingManifestPath =
        $Main.PendingManifestPath

    if (-not (Test-Path $PendingManifestPath)) {
        throw "STOP: Pending UE 5.8 manifest was not found: $PendingManifestPath"
    }

    $PendingManifestHash =
        (Get-FileHash `
            $PendingManifestPath `
            -Algorithm SHA256).Hash

    Write-Host ""
    Write-Host "[7] Pending manifest"
    Write-Host "Path   : $PendingManifestPath"
    Write-Host "SHA256 : $PendingManifestHash"


    # ============================================================
    # 9. VALIDATE CURRENT METADATA VERSION
    # ============================================================

    $AllowedInstalledVersions =
        @(
            $PreviousAppVersion,
            $ExpectedAppVersion
        )

    if ($Main.AppVersionString -notin $AllowedInstalledVersions) {
        throw "STOP: Installed metadata contains an unexpected UE_5.8 version."
    }

    if ($UE58.AppVersion -notin $AllowedInstalledVersions) {
        throw "STOP: LauncherInstalled.dat contains an unexpected UE_5.8 version."
    }


    # ============================================================
    # 10. SIMULATE THE MANIFEST COMMIT IN MEMORY
    # ============================================================

    $SimMain =
        Read-JsonFile $MainItemPath

    $SimMain.AppVersionString =
        $Pending.AppVersionString

    $SimMain.PrereqSHA1Hash =
        $Pending.PrereqSHA1Hash

    $SimMain.bIsIncompleteInstall =
        $false


    $SimLauncher =
        Read-JsonFile $LauncherDat

    $SimEntries = @(
        $SimLauncher.InstallationList |
        Where-Object {
            $_.AppName -eq "UE_5.8"
        }
    )

    if ($SimEntries.Count -ne 1) {
        throw "STOP: Simulation could not uniquely resolve UE_5.8."
    }

    $SimEntries[0].AppVersion =
        $ExpectedAppVersion


    # Serialize + parse again to verify that resulting JSON remains valid.

    $SimMainJson =
        $SimMain |
        ConvertTo-Json -Depth 20

    $SimLauncherJson =
        $SimLauncher |
        ConvertTo-Json -Depth 20

    $ParsedMain =
        $SimMainJson |
        ConvertFrom-Json

    $ParsedLauncher =
        $SimLauncherJson |
        ConvertFrom-Json

    $ParsedUE58 = @(
        $ParsedLauncher.InstallationList |
        Where-Object {
            $_.AppName -eq "UE_5.8"
        }
    )

    if ($ParsedMain.AppVersionString -ne $ExpectedAppVersion) {
        throw "STOP: In-memory installed metadata simulation failed."
    }

    if ($ParsedMain.PrereqSHA1Hash -ne $Pending.PrereqSHA1Hash) {
        throw "STOP: In-memory PrereqSHA1Hash simulation failed."
    }

    if ($ParsedMain.bIsIncompleteInstall -ne $false) {
        throw "STOP: Simulated installed metadata remains incomplete."
    }

    if (
        $ParsedUE58.Count -ne 1 -or
        $ParsedUE58[0].AppVersion -ne $ExpectedAppVersion
    ) {
        throw "STOP: LauncherInstalled.dat simulation failed."
    }


    # ============================================================
    # DRY RUN RESULT
    # ============================================================

    Write-Host ""
    Write-Host "==========================================="
    Write-Host " STATUS: AFFECTED / CONDITIONS MATCH"
    Write-Host "==========================================="
    Write-Host ""
    Write-Host "Physical Engine:"
    Write-Host "  UE 5.8.2 / CL $ExpectedCL"
    Write-Host ""
    Write-Host "Installed metadata:"
    Write-Host "  $($Main.AppVersionString)"
    Write-Host ""
    Write-Host "Pending target:"
    Write-Host "  $($Pending.AppVersionString)"
    Write-Host ""
    Write-Host "LauncherInstalled.dat:"
    Write-Host "  $($UE58.AppVersion)"
    Write-Host ""
    Write-Host "In-memory commit simulation:"
    Write-Host "  PASSED"


    if (-not $ApplyChanges) {

        Write-Host ""
        Write-Host "==========================================="
        Write-Host " DRY RUN PASSED"
        Write-Host "==========================================="
        Write-Host "No files were modified, copied or deleted."
        Write-Host ""
        Write-Host "To apply the workaround:"
        Write-Host ""
        Write-Host 'Change: $ApplyChanges = $false'
        Write-Host 'To:     $ApplyChanges = $true'
        Write-Host ""
        Write-Host "Then run THIS SAME script again while"
        Write-Host "the Launcher is still in the Resume state."
        Write-Host "==========================================="

        return
    }


    # ============================================================
    # APPLY MODE
    # ============================================================
    #
    # From this point on changes are allowed.
    #
    # First create a complete backup while the Pending transaction
    # still exists. Only after that will the user be asked to close
    # Epic Games Launcher.
    #
    # ============================================================

    Write-Host ""
    Write-Host "==========================================="
    Write-Host " APPLY MODE - CREATING BACKUP"
    Write-Host "==========================================="


    $Desktop =
        [Environment]::GetFolderPath(
            [Environment+SpecialFolder]::Desktop
        )

    $Stamp =
        Get-Date -Format "yyyyMMdd_HHmmss"

    $BackupDir =
        Join-Path `
            $Desktop `
            "UE58_LauncherBackup_$Stamp"

    New-Item `
        -Path $BackupDir `
        -ItemType Directory |
        Out-Null


    Copy-Item `
        -LiteralPath $MainItemPath `
        -Destination (Join-Path $BackupDir "installed.item")

    Copy-Item `
        -LiteralPath $PendingItemPath `
        -Destination (Join-Path $BackupDir "pending.item")

    Copy-Item `
        -LiteralPath $Main.CompleteManifestPath `
        -Destination (Join-Path $BackupDir "installed.manifest")

    Copy-Item `
        -LiteralPath $PendingManifestPath `
        -Destination (Join-Path $BackupDir "pending.manifest")

    Copy-Item `
        -LiteralPath $LauncherDat `
        -Destination (Join-Path $BackupDir "LauncherInstalled.dat")

    Copy-Item `
        -LiteralPath $BuildVersionPath `
        -Destination (Join-Path $BackupDir "Build.version")


    Write-Host ""
    Write-Host "BACKUP CREATED:"
    Write-Host $BackupDir
    Write-Host ""
    Write-Host "Do NOT delete this backup until Epic provides"
    Write-Host "an official fix or you are satisfied with the result."


    # ============================================================
    # USER CONFIRMATION
    # ============================================================

    Write-Host ""
    Write-Host "Now completely EXIT Epic Games Launcher,"
    Write-Host "including the system tray icon."
    Write-Host ""
    Write-Host "The Pending files may disappear when Launcher exits."
    Write-Host "That is OK - copies are already stored in the backup."
    Write-Host ""

    $Confirm =
        Read-Host "After Launcher is fully closed, type APPLY"

    if ($Confirm -cne "APPLY") {
        Write-Host ""
        Write-Host "Cancelled."
        Write-Host "No Launcher metadata was modified."
        Write-Host "The backup directory was kept:"
        Write-Host $BackupDir

        return
    }


    # ============================================================
    # VERIFY LAUNCHER IS REALLY CLOSED
    # ============================================================

    $Running =
        Get-Process `
            EpicGamesLauncher,
            EpicWebHelper `
            -ErrorAction SilentlyContinue

    if ($Running) {
        throw "STOP: Epic Games Launcher or EpicWebHelper is still running. No metadata commit was performed."
    }


    # ============================================================
    # RE-READ BACKUP SOURCES
    # ============================================================

    $BackupMain =
        Read-JsonFile `
            (Join-Path $BackupDir "installed.item")

    $BackupPending =
        Read-JsonFile `
            (Join-Path $BackupDir "pending.item")


    if ($BackupPending.AppVersionString -ne $ExpectedAppVersion) {
        throw "STOP: Backup Pending metadata is not the expected UE 5.8.2 build."
    }


    # ============================================================
    # 11. PROMOTE COMPLETED PENDING MANIFEST TO INSTALLED MANIFEST
    # ============================================================

    Copy-Item `
        -LiteralPath (Join-Path $BackupDir "pending.manifest") `
        -Destination $BackupMain.CompleteManifestPath `
        -Force


    # ============================================================
    # 12. COMMIT INSTALLED ITEM METADATA
    # ============================================================

    #
    # Keep the structure and install options from the original
    # installed item.
    #
    # Only promote fields that are known to belong to the new build.
    #

    $BackupMain.AppVersionString =
        $BackupPending.AppVersionString

    $BackupMain.PrereqSHA1Hash =
        $BackupPending.PrereqSHA1Hash

    $BackupMain.bIsIncompleteInstall =
        $false


    $CommittedItemJson =
        $BackupMain |
        ConvertTo-Json -Depth 20


    $Utf8NoBom =
        New-Object System.Text.UTF8Encoding($false)

    [IO.File]::WriteAllText(
        $MainItemPath,
        $CommittedItemJson,
        $Utf8NoBom
    )


    # ============================================================
    # 13. UPDATE LauncherInstalled.dat
    # ============================================================

    #
    # Re-read the current file after Launcher shutdown so that
    # unrelated Launcher entries are preserved.
    #

    $CurrentLauncher =
        Read-JsonFile $LauncherDat

    $CurrentUE58 = @(
        $CurrentLauncher.InstallationList |
        Where-Object {
            $_.AppName -eq "UE_5.8"
        }
    )

    if ($CurrentUE58.Count -ne 1) {
        throw "STOP: UE_5.8 could not be uniquely resolved in LauncherInstalled.dat."
    }

    $CurrentUE58[0].AppVersion =
        $ExpectedAppVersion


    $CommittedLauncherJson =
        $CurrentLauncher |
        ConvertTo-Json -Depth 20

    [IO.File]::WriteAllText(
        $LauncherDat,
        $CommittedLauncherJson,
        $Utf8NoBom
    )


    # ============================================================
    # 14. REMOVE ONLY THE UE_5.8 PENDING TRANSACTION
    # ============================================================

    #
    # Launcher may already have removed these files on shutdown.
    # Therefore existence is checked first.
    #

    if (Test-Path $PendingItemPath) {
        Remove-Item `
            -LiteralPath $PendingItemPath
    }

    if (Test-Path $PendingManifestPath) {
        Remove-Item `
            -LiteralPath $PendingManifestPath
    }


    # ============================================================
    # 15. FINAL VERIFICATION
    # ============================================================

    $FinalMain =
        Read-JsonFile $MainItemPath

    $FinalLauncher =
        Read-JsonFile $LauncherDat

    $FinalUE58 = @(
        $FinalLauncher.InstallationList |
        Where-Object {
            $_.AppName -eq "UE_5.8"
        }
    )

    if ($FinalMain.AppVersionString -ne $ExpectedAppVersion) {
        throw "FINAL VERIFY FAILED: installed item version mismatch."
    }

    if ($FinalMain.bIsIncompleteInstall -ne $false) {
        throw "FINAL VERIFY FAILED: installed item is still incomplete."
    }

    if ($FinalMain.PrereqSHA1Hash -ne $BackupPending.PrereqSHA1Hash) {
        throw "FINAL VERIFY FAILED: PrereqSHA1Hash mismatch."
    }

    if (
        $FinalUE58.Count -ne 1 -or
        $FinalUE58[0].AppVersion -ne $ExpectedAppVersion
    ) {
        throw "FINAL VERIFY FAILED: LauncherInstalled.dat mismatch."
    }


    $FinalInstalledManifestHash =
        (Get-FileHash `
            $FinalMain.CompleteManifestPath `
            -Algorithm SHA256).Hash

    $BackupPendingManifestHash =
        (Get-FileHash `
            (Join-Path $BackupDir "pending.manifest") `
            -Algorithm SHA256).Hash

    if ($FinalInstalledManifestHash -ne $BackupPendingManifestHash) {
        throw "FINAL VERIFY FAILED: installed manifest does not match the completed Pending manifest."
    }


    Write-Host ""
    Write-Host "==========================================="
    Write-Host " WORKAROUND COMPLETED SUCCESSFULLY"
    Write-Host "==========================================="
    Write-Host ""
    Write-Host "Installed metadata:"
    Write-Host "  $($FinalMain.AppVersionString)"
    Write-Host ""
    Write-Host "Incomplete:"
    Write-Host "  $($FinalMain.bIsIncompleteInstall)"
    Write-Host ""
    Write-Host "LauncherInstalled.dat:"
    Write-Host "  $($FinalUE58[0].AppVersion)"
    Write-Host ""
    Write-Host "Pending item exists:"
    Write-Host "  $(Test-Path $PendingItemPath)"
    Write-Host ""
    Write-Host "Pending manifest exists:"
    Write-Host "  $(Test-Path $PendingManifestPath)"
    Write-Host ""
    Write-Host "Installed manifest SHA256:"
    Write-Host "  $FinalInstalledManifestHash"
    Write-Host ""
    Write-Host "Backup:"
    Write-Host "  $BackupDir"
    Write-Host ""
    Write-Host "You can now start Epic Games Launcher."
    Write-Host "It should display Unreal Engine 5.8.2 / Launch."
    Write-Host "==========================================="
}

Validation

Before publishing this workaround I tested the script in several modes.

  • The default read-only mode was tested against my repaired installation and correctly returned STATUS: ALREADY HEALTHY without modifying anything.
  • ApplyChanges = $true was also tested against the healthy installation and correctly exited without making changes.
  • The complete Apply workflow was then tested in an isolated sandbox created from the original files captured while the Launcher was affected:
Installed metadata: 5.8.1
Pending target:      5.8.2
Launcher metadata:   5.8.1

The sandbox test successfully performed the backup, manifest promotion, metadata reconciliation and Pending cleanup.

Final verification confirmed that the installed manifest SHA256 was identical to the original 5.8.2 Pending manifest SHA256:

9CB3C546C7D3C8C111D6D8AD69FE090714F5304FF1F81E099BD95B9F7493C86D

The real Epic Games Launcher and Unreal Engine installation were not modified during this sandbox test.

1 Like

Thanks for the share and getting down and dirty on the technicals. Just so you’re aware, this same behavior was kicking in with 5.8.2 → 5.8.3. Multiple update loops, couldn’t update plugins, etc. I tried several “fixes” to no avail, and was about to modify what you shared - but then magically seem to wake up and smell the roses.

Epic really needs to pin this down and squash this and related bugs ASAP. It’s affecting many people, it’s not a fringe issue. It seems to be loosely related to plugin update notification issues as well, where there are no actual updates to plugins, but launcher says there is. Or when users click on update, and nothing happens.

2 Likes

Thanks for the report, we have a ticket in.

1 Like

Update: reproduced again with UE 5.8.3

I have now reproduced the same issue again while updating from UE 5.8.2 to UE 5.8.3.

Before starting the update, the installation was fully healthy:

Launcher metadata:      5.8.2-56702186
UnrealEditor.exe:       5.8.2.0 / CL-56702186
Build.version:          5.8.2 / CL-56702186
Pending item:           none
Pending manifest:       none

I then clicked Update once. The update downloaded and completed, but Epic Games Launcher returned to:

Unreal Engine 5.8.2
Resume

However, the physical Engine files were already updated successfully:

UnrealEditor.exe:
Numeric version: 5.8.3.0
ProductVersion: ++UE5+Release-5.8-CL-58210709

Engine\Build\Build.version:
Version: 5.8.3
Changelist: 58210709

Launcher metadata remained on:

5.8.2-56702186+++UE5+Release-5.8-Windows

while a new Pending transaction was created for:

5.8.3-58210709+++UE5+Release-5.8-Windows
bIsIncompleteInstall=True

The log shows the expected transition:

5.8.2-56702186 -> 5.8.3-58210709
Action: Update

and:

CurrentManifest: 5.8.2-56702186
InstallManifest: 5.8.3-58210709

BuildPatch then completes successfully:

ProcessSuccess: TRUE
ErrorCode: OK
FailureReasonText: The operation was successful.

but immediately afterwards:

IncompleteInstall=1 AutoResume=1
completed, waiting for manifest commit before starting next download

So this appears to reproduce the same manifest-commit failure on the next hotfix, not just the original 5.8.1 → 5.8.2 update.

One additional finding: the earlier 5.8.2 reproduction logged:

MainGameAppId mismatch
catalog=(null):(null):(null)
Correcting to catalog value

In the 5.8.3 reproduction this has changed to:

MainGameAppId mismatch
catalog=(empty)
Keeping on-disk value

Despite that changed handling, the manifest commit still fails. This suggests the MainGameAppId warning may not be the primary cause of the Resume loop.

I have preserved the complete 5.8.3 Pending .item, Pending manifest, installed manifest, Launcher metadata and Launcher log for the existing ticket.

Update: v2.0 generic UE 5.8.x workaround confirmed on 5.8.3

I have now reproduced the same Launcher manifest-commit failure again while updating from UE 5.8.2 to UE 5.8.3.

The first Update successfully installed the physical Engine files:

UnrealEditor.exe:
5.8.3.0
++UE5+Release-5.8-CL-58210709

Engine\Build\Build.version:
5.8.3
CL 58210709

but Epic Games Launcher remained on:

UE 5.8.2
Resume

with a new Pending transaction for:

5.8.3-58210709+++UE5+Release-5.8-Windows
bIsIncompleteInstall=True

I therefore updated the workaround script to v2.0.

What changed in v2.0

v2.0 no longer hardcodes a specific hotfix such as 5.8.2 or 5.8.3.

Instead, it:

  • detects the target UE 5.8.x version automatically from the active Pending transaction,
  • extracts the target patch version and changelist,
  • verifies that target independently against UnrealEditor.exe,
  • verifies it again against Engine\Build\Build.version,
  • checks LauncherInstalled.dat,
  • checks both installed and Pending manifests,
  • simulates the metadata commit in memory first,
  • runs in DRY-RUN / READ-ONLY mode by default,
  • creates a full backup before Apply mode,
  • requires explicit APPLY confirmation,
  • promotes the Pending manifest only after all validations pass,
  • updates only the UE 5.8-specific metadata,
  • removes only the matching UE 5.8 Pending transaction,
  • verifies the final manifest SHA256.

Validation

v2.0 was tested end-to-end on this real UE 5.8.2 → 5.8.3 failure.

Before Apply:

Installed metadata:
  5.8.2-56702186

Physical Engine:
  5.8.3 / CL 58210709

Pending target:
  5.8.3-58210709

LauncherInstalled.dat:
  5.8.2-56702186

DRY-RUN result:

STATUS: AFFECTED / CONDITIONS MATCH
Target verification: MATCH
In-memory commit simulation: PASSED
DRY RUN PASSED

Apply result:

WORKAROUND COMPLETED SUCCESSFULLY

Committed Engine:
  UE 5.8.3 / CL 58210709

Installed metadata:
  5.8.3-58210709+++UE5+Release-5.8-Windows

Incomplete:
  False

LauncherInstalled.dat:
  5.8.3-58210709+++UE5+Release-5.8-Windows

Pending item exists:
  False

Pending manifest exists:
  False

Final manifest verification:

Installed manifest SHA256:
65619BCDBC675EC4CE4C9D349B7CAAA7DA3F281A2085A2D0070533C0893BD06A

Target Pending manifest SHA256:
65619BCDBC675EC4CE4C9D349B7CAAA7DA3F281A2085A2D0070533C0893BD06A

After restarting Epic Games Launcher, it correctly displayed:

Unreal Engine 5.8.3
Launch

No additional Engine download was required.

Important

This is still an unofficial workaround, not an Epic fix.

The script is deliberately read-only by default:

$ApplyChanges = $false

Only change it to $true if DRY-RUN confirms that the physical Engine already matches the Pending target exactly.

 & {
    $ErrorActionPreference = "Stop"
    Set-StrictMode -Version Latest


    # ============================================================
    # UE 5.8.x LAUNCHER MANIFEST DIAGNOSTIC / WORKAROUND
    # Version 2.0
    # ============================================================
    #
    # DEFAULT = SAFE / READ-ONLY
    #
    # Leave this as $false first.
    #
    # Change to $true ONLY after DRY RUN PASSED and only if the
    # system matches the manifest-commit issue described here.
    #
    # This version automatically detects the target UE 5.8.x
    # hotfix and changelist from the Pending transaction.
    #
    # ============================================================

    $ApplyChanges = $false


    # ============================================================
    # SUPPORTED ENGINE BRANCH
    # ============================================================

    $SupportedMajor = 5
    $SupportedMinor = 8
    $ExpectedAppName = "UE_5.8"


    # ============================================================
    # EPIC LAUNCHER PATHS
    # ============================================================

    $ManifestRoot =
        "C:\ProgramData\Epic\EpicGamesLauncher\Data\Manifests"

    $PendingRoot =
        Join-Path $ManifestRoot "Pending"

    $LauncherDat =
        "C:\ProgramData\Epic\UnrealEngineLauncher\LauncherInstalled.dat"


    # ============================================================
    # HELPERS
    # ============================================================

    function Read-JsonFile {
        param(
            [Parameter(Mandatory = $true)]
            [string]$Path
        )

        Get-Content -LiteralPath $Path -Raw |
            ConvertFrom-Json
    }


    function Parse-UeAppVersion {
        param(
            [Parameter(Mandatory = $true)]
            [string]$VersionString
        )

        #
        # Example:
        #
        # 5.8.3-58210709+++UE5+Release-5.8-Windows
        #

        $Pattern =
            '^(?<Major>\d+)\.(?<Minor>\d+)\.(?<Patch>\d+)-(?<CL>\d+)\+\+\+UE5\+Release-(?<BranchMajor>\d+)\.(?<BranchMinor>\d+)-Windows$'

        $Match =
            [regex]::Match(
                $VersionString,
                $Pattern
            )

        if (-not $Match.Success) {
            throw "STOP: Unsupported AppVersionString format: $VersionString"
        }

        [PSCustomObject]@{
            Raw         = $VersionString
            Major       = [int]$Match.Groups["Major"].Value
            Minor       = [int]$Match.Groups["Minor"].Value
            Patch       = [int]$Match.Groups["Patch"].Value
            CL          = [int64]$Match.Groups["CL"].Value
            BranchMajor = [int]$Match.Groups["BranchMajor"].Value
            BranchMinor = [int]$Match.Groups["BranchMinor"].Value
        }
    }


    function Get-SemVersion {
        param($Parsed)

        [version](
            "{0}.{1}.{2}" -f `
            $Parsed.Major,
            $Parsed.Minor,
            $Parsed.Patch
        )
    }


    Write-Host ""
    Write-Host "================================================"
    Write-Host " UE 5.8.x LAUNCHER MANIFEST DIAGNOSTIC v2.0"
    Write-Host "================================================"

    if ($ApplyChanges) {
        Write-Host "MODE: APPLY CHANGES"
    }
    else {
        Write-Host "MODE: DRY RUN / READ-ONLY"
    }


    # ============================================================
    # 1. FIND INSTALLED UE_5.8 ITEM
    # ============================================================

    if (-not (Test-Path -LiteralPath $ManifestRoot)) {
        throw "STOP: Epic Games Launcher manifest directory was not found."
    }

    $MainCandidates = @()

    foreach (
        $File in
        Get-ChildItem `
            -LiteralPath $ManifestRoot `
            -Filter "*.item" `
            -File
    ) {
        try {
            $Data =
                Read-JsonFile $File.FullName

            if ($Data.AppName -eq $ExpectedAppName) {
                $MainCandidates +=
                    [PSCustomObject]@{
                        Path = $File.FullName
                        Data = $Data
                    }
            }
        }
        catch {
        }
    }


    if ($MainCandidates.Count -ne 1) {
        throw "STOP: Expected exactly one installed $ExpectedAppName item, found $($MainCandidates.Count)."
    }


    $MainItemPath =
        $MainCandidates[0].Path

    $Main =
        $MainCandidates[0].Data


    if ([string]::IsNullOrWhiteSpace($Main.AppVersionString)) {
        throw "STOP: Installed AppVersionString is empty."
    }


    $InstalledVersion =
        Parse-UeAppVersion $Main.AppVersionString


    if (
        $InstalledVersion.Major -ne $SupportedMajor -or
        $InstalledVersion.Minor -ne $SupportedMinor -or
        $InstalledVersion.BranchMajor -ne $SupportedMajor -or
        $InstalledVersion.BranchMinor -ne $SupportedMinor
    ) {
        throw "STOP: Installed metadata is not UE $SupportedMajor.$SupportedMinor.x."
    }


    Write-Host ""
    Write-Host "[1] Installed UE_5.8 metadata"
    Write-Host "Item       : $MainItemPath"
    Write-Host "Version    : $($Main.AppVersionString)"
    Write-Host "Parsed     : $($InstalledVersion.Major).$($InstalledVersion.Minor).$($InstalledVersion.Patch)"
    Write-Host "CL         : $($InstalledVersion.CL)"
    Write-Host "Incomplete : $($Main.bIsIncompleteInstall)"
    Write-Host "Location   : $($Main.InstallLocation)"


    # ============================================================
    # 2. FIND ACTIVE UE_5.8 PENDING TRANSACTION
    # ============================================================

    $PendingCandidates = @()

    if (Test-Path -LiteralPath $PendingRoot) {

        foreach (
            $File in
            Get-ChildItem `
                -LiteralPath $PendingRoot `
                -Filter "*.item" `
                -File `
                -ErrorAction SilentlyContinue
        ) {
            try {
                $Data =
                    Read-JsonFile $File.FullName

                if ($Data.AppName -eq $ExpectedAppName) {
                    $PendingCandidates +=
                        [PSCustomObject]@{
                            Path = $File.FullName
                            Data = $Data
                        }
                }
            }
            catch {
            }
        }
    }


    # ============================================================
    # 3. VERIFY PHYSICAL ENGINE
    # ============================================================

    if ([string]::IsNullOrWhiteSpace($Main.InstallLocation)) {
        throw "STOP: UE_5.8 InstallLocation is empty."
    }


    $EditorExe =
        Join-Path `
            $Main.InstallLocation `
            "Engine\Binaries\Win64\UnrealEditor.exe"

    $BuildVersionPath =
        Join-Path `
            $Main.InstallLocation `
            "Engine\Build\Build.version"


    if (-not (Test-Path -LiteralPath $EditorExe)) {
        throw "STOP: UnrealEditor.exe was not found."
    }

    if (-not (Test-Path -LiteralPath $BuildVersionPath)) {
        throw "STOP: Engine\Build\Build.version was not found."
    }


    $VI =
        (Get-Item -LiteralPath $EditorExe).VersionInfo

    $Build =
        Read-JsonFile $BuildVersionPath


    $PhysicalVersion =
        [version](
            "{0}.{1}.{2}" -f `
            $VI.FileMajorPart,
            $VI.FileMinorPart,
            $VI.FileBuildPart
        )


    $NumericFileVersion =
        "{0}.{1}.{2}.{3}" -f `
            $VI.FileMajorPart,
            $VI.FileMinorPart,
            $VI.FileBuildPart,
            $VI.FilePrivatePart


    Write-Host ""
    Write-Host "[2] Physical Unreal Engine"
    Write-Host "Numeric FileVersion : $NumericFileVersion"
    Write-Host "FileVersion string  : $($VI.FileVersion)"
    Write-Host "ProductVersion      : $($VI.ProductVersion)"
    Write-Host "Build.version       : $($Build.MajorVersion).$($Build.MinorVersion).$($Build.PatchVersion)"
    Write-Host "Build CL            : $($Build.Changelist)"


    if (
        $VI.FileMajorPart -ne $SupportedMajor -or
        $VI.FileMinorPart -ne $SupportedMinor
    ) {
        throw "STOP: Physical Engine is not UE $SupportedMajor.$SupportedMinor.x."
    }


    if (
        $Build.MajorVersion -ne $VI.FileMajorPart -or
        $Build.MinorVersion -ne $VI.FileMinorPart -or
        $Build.PatchVersion -ne $VI.FileBuildPart
    ) {
        throw "STOP: UnrealEditor.exe and Build.version disagree about the Engine version."
    }


    # ============================================================
    # 4. VERIFY INSTALLED MANIFEST
    # ============================================================

    if ([string]::IsNullOrWhiteSpace($Main.CompleteManifestPath)) {
        throw "STOP: CompleteManifestPath is empty."
    }


    if (-not (Test-Path -LiteralPath $Main.CompleteManifestPath)) {
        throw "STOP: Installed manifest was not found: $($Main.CompleteManifestPath)"
    }


    $InstalledManifestHash =
        (Get-FileHash `
            -LiteralPath $Main.CompleteManifestPath `
            -Algorithm SHA256).Hash


    Write-Host ""
    Write-Host "[3] Installed manifest"
    Write-Host "Path   : $($Main.CompleteManifestPath)"
    Write-Host "SHA256 : $InstalledManifestHash"


    # ============================================================
    # 5. READ LauncherInstalled.dat
    # ============================================================

    if (-not (Test-Path -LiteralPath $LauncherDat)) {
        throw "STOP: LauncherInstalled.dat was not found."
    }


    $Launcher =
        Read-JsonFile $LauncherDat


    $LauncherEntries = @(
        $Launcher.InstallationList |
        Where-Object {
            $_.AppName -eq $ExpectedAppName
        }
    )


    if ($LauncherEntries.Count -ne 1) {
        throw "STOP: Expected exactly one $ExpectedAppName entry in LauncherInstalled.dat."
    }


    $LauncherUE58 =
        $LauncherEntries[0]


    $LauncherVersion =
        Parse-UeAppVersion $LauncherUE58.AppVersion


    Write-Host ""
    Write-Host "[4] LauncherInstalled.dat"
    Write-Host "Version : $($LauncherUE58.AppVersion)"


    # ============================================================
    # 6. ALREADY HEALTHY?
    # ============================================================

    if ($PendingCandidates.Count -eq 0) {

        $BuildSemVer =
            [version](
                "{0}.{1}.{2}" -f `
                $Build.MajorVersion,
                $Build.MinorVersion,
                $Build.PatchVersion
            )


        $InstalledSemVer =
            Get-SemVersion $InstalledVersion


        $LauncherSemVer =
            Get-SemVersion $LauncherVersion


        if (
            $InstalledSemVer -eq $BuildSemVer -and
            $LauncherSemVer -eq $BuildSemVer -and
            $Main.bIsIncompleteInstall -eq $false -and
            $InstalledVersion.CL -eq [int64]$Build.Changelist -and
            $LauncherVersion.CL -eq [int64]$Build.Changelist
        ) {

            Write-Host ""
            Write-Host "================================================"
            Write-Host " STATUS: ALREADY HEALTHY"
            Write-Host "================================================"
            Write-Host "Physical Engine and Launcher metadata agree:"
            Write-Host (
                "UE {0}.{1}.{2} / CL {3}" -f `
                $Build.MajorVersion,
                $Build.MinorVersion,
                $Build.PatchVersion,
                $Build.Changelist
            )
            Write-Host ""
            Write-Host "No active UE 5.8 Pending transaction exists."
            Write-Host "No changes were made."
            Write-Host "================================================"

            return
        }


        Write-Host ""
        Write-Host "================================================"
        Write-Host " STATUS: PHYSICAL ENGINE / METADATA MISMATCH"
        Write-Host "================================================"
        Write-Host "Physical Engine is newer or different from"
        Write-Host "Launcher metadata, but no Pending transaction"
        Write-Host "is currently available."
        Write-Host ""
        Write-Host "No changes were made."
        Write-Host ""
        Write-Host "If Launcher is showing Update/Resume, start"
        Write-Host "that operation once and run this script again"
        Write-Host "while the Pending transaction still exists."
        Write-Host "================================================"

        return
    }


    if ($PendingCandidates.Count -ne 1) {
        throw "STOP: More than one UE_5.8 Pending item was found."
    }


    $PendingItemPath =
        $PendingCandidates[0].Path

    $Pending =
        $PendingCandidates[0].Data


    if ([string]::IsNullOrWhiteSpace($Pending.AppVersionString)) {
        throw "STOP: Pending AppVersionString is empty."
    }


    $Target =
        Parse-UeAppVersion $Pending.AppVersionString


    Write-Host ""
    Write-Host "[5] Active Pending transaction"
    Write-Host "Item       : $PendingItemPath"
    Write-Host "Version    : $($Pending.AppVersionString)"
    Write-Host "Target     : $($Target.Major).$($Target.Minor).$($Target.Patch)"
    Write-Host "Target CL  : $($Target.CL)"
    Write-Host "Incomplete : $($Pending.bIsIncompleteInstall)"
    Write-Host "PrereqSHA1 : $($Pending.PrereqSHA1Hash)"


    # ============================================================
    # 7. VALIDATE TARGET BRANCH
    # ============================================================

    if (
        $Target.Major -ne $SupportedMajor -or
        $Target.Minor -ne $SupportedMinor -or
        $Target.BranchMajor -ne $SupportedMajor -or
        $Target.BranchMinor -ne $SupportedMinor
    ) {
        throw "STOP: Pending target is outside the supported UE 5.8.x branch."
    }


    if ($Pending.bIsIncompleteInstall -ne $true) {
        throw "STOP: Pending UE_5.8 item is not marked as incomplete."
    }


    if (
        [string]::IsNullOrWhiteSpace($Pending.PrereqSHA1Hash) -or
        $Pending.PrereqSHA1Hash -notmatch '^[0-9A-Fa-f]{40}$'
    ) {
        throw "STOP: Pending PrereqSHA1Hash is invalid."
    }


    if (
        -not [string]::IsNullOrWhiteSpace($Pending.InstallLocation) -and
        $Pending.InstallLocation -ne $Main.InstallLocation
    ) {
        throw "STOP: Pending InstallLocation does not match installed UE_5.8."
    }


    $InstalledSemVer =
        Get-SemVersion $InstalledVersion

    $TargetSemVer =
        Get-SemVersion $Target


    if ($InstalledSemVer -gt $TargetSemVer) {
        throw "STOP: Installed Launcher metadata is newer than the Pending target."
    }


    # ============================================================
    # 8. VERIFY TARGET AGAINST PHYSICAL ENGINE
    # ============================================================

    if ($PhysicalVersion -ne $TargetSemVer) {
        throw (
            "STOP: Physical UnrealEditor.exe version " +
            "$PhysicalVersion does not match Pending target $TargetSemVer."
        )
    }


    if (
        $Build.MajorVersion -ne $Target.Major -or
        $Build.MinorVersion -ne $Target.Minor -or
        $Build.PatchVersion -ne $Target.Patch -or
        [int64]$Build.Changelist -ne $Target.CL
    ) {
        throw "STOP: Build.version does not match the Pending target."
    }


    if ($VI.ProductVersion -notlike "*CL-$($Target.CL)*") {
        throw "STOP: UnrealEditor.exe ProductVersion does not match Pending target CL $($Target.CL)."
    }


    Write-Host ""
    Write-Host "[6] Target verification"
    Write-Host "Pending target     : $TargetSemVer / CL $($Target.CL)"
    Write-Host "UnrealEditor.exe   : $PhysicalVersion / CL $($Target.CL)"
    Write-Host "Build.version      : $($Build.MajorVersion).$($Build.MinorVersion).$($Build.PatchVersion) / CL $($Build.Changelist)"
    Write-Host "Result             : MATCH"


    # ============================================================
    # 9. LOCATE PENDING MANIFEST
    # ============================================================

    if ([string]::IsNullOrWhiteSpace($Main.PendingManifestPath)) {
        throw "STOP: Installed UE_5.8 item has no PendingManifestPath."
    }


    $PendingManifestPath =
        $Main.PendingManifestPath


    if (-not (Test-Path -LiteralPath $PendingManifestPath)) {
        throw "STOP: Pending manifest was not found: $PendingManifestPath"
    }


    $PendingManifestHash =
        (Get-FileHash `
            -LiteralPath $PendingManifestPath `
            -Algorithm SHA256).Hash


    Write-Host ""
    Write-Host "[7] Pending manifest"
    Write-Host "Path   : $PendingManifestPath"
    Write-Host "SHA256 : $PendingManifestHash"


    # ============================================================
    # 10. VALIDATE LauncherInstalled.dat VERSION
    # ============================================================

    $LauncherSemVer =
        Get-SemVersion $LauncherVersion


    if ($LauncherSemVer -gt $TargetSemVer) {
        throw "STOP: LauncherInstalled.dat is newer than the Pending target."
    }


    if (
        $LauncherVersion.Major -ne $SupportedMajor -or
        $LauncherVersion.Minor -ne $SupportedMinor
    ) {
        throw "STOP: LauncherInstalled.dat is outside UE 5.8.x."
    }


    # ============================================================
    # 11. SIMULATE COMMIT IN MEMORY
    # ============================================================

    $SimMain =
        Read-JsonFile $MainItemPath


    $SimMain.AppVersionString =
        $Pending.AppVersionString

    $SimMain.PrereqSHA1Hash =
        $Pending.PrereqSHA1Hash

    $SimMain.bIsIncompleteInstall =
        $false


    $SimLauncher =
        Read-JsonFile $LauncherDat


    $SimLauncherEntries = @(
        $SimLauncher.InstallationList |
        Where-Object {
            $_.AppName -eq $ExpectedAppName
        }
    )


    if ($SimLauncherEntries.Count -ne 1) {
        throw "STOP: Simulation could not uniquely resolve UE_5.8."
    }


    $SimLauncherEntries[0].AppVersion =
        $Pending.AppVersionString


    $SimMainJson =
        $SimMain |
        ConvertTo-Json -Depth 20

    $SimLauncherJson =
        $SimLauncher |
        ConvertTo-Json -Depth 20


    $ParsedMain =
        $SimMainJson |
        ConvertFrom-Json

    $ParsedLauncher =
        $SimLauncherJson |
        ConvertFrom-Json


    $ParsedEntries = @(
        $ParsedLauncher.InstallationList |
        Where-Object {
            $_.AppName -eq $ExpectedAppName
        }
    )


    if ($ParsedMain.AppVersionString -ne $Pending.AppVersionString) {
        throw "STOP: In-memory installed metadata simulation failed."
    }


    if ($ParsedMain.PrereqSHA1Hash -ne $Pending.PrereqSHA1Hash) {
        throw "STOP: In-memory PrereqSHA1Hash simulation failed."
    }


    if ($ParsedMain.bIsIncompleteInstall -ne $false) {
        throw "STOP: Simulated installed metadata remains incomplete."
    }


    if (
        $ParsedEntries.Count -ne 1 -or
        $ParsedEntries[0].AppVersion -ne $Pending.AppVersionString
    ) {
        throw "STOP: LauncherInstalled.dat simulation failed."
    }


    # ============================================================
    # DIAGNOSTIC RESULT
    # ============================================================

    Write-Host ""
    Write-Host "================================================"
    Write-Host " STATUS: AFFECTED / CONDITIONS MATCH"
    Write-Host "================================================"
    Write-Host ""
    Write-Host "Launcher installed metadata:"
    Write-Host "  $($Main.AppVersionString)"
    Write-Host ""
    Write-Host "Physical Engine:"
    Write-Host "  UE $TargetSemVer / CL $($Target.CL)"
    Write-Host ""
    Write-Host "Pending target:"
    Write-Host "  $($Pending.AppVersionString)"
    Write-Host ""
    Write-Host "LauncherInstalled.dat:"
    Write-Host "  $($LauncherUE58.AppVersion)"
    Write-Host ""
    Write-Host "Installed manifest SHA256:"
    Write-Host "  $InstalledManifestHash"
    Write-Host ""
    Write-Host "Pending manifest SHA256:"
    Write-Host "  $PendingManifestHash"
    Write-Host ""
    Write-Host "In-memory commit simulation:"
    Write-Host "  PASSED"


    # ============================================================
    # DRY RUN STOP
    # ============================================================

    if (-not $ApplyChanges) {

        Write-Host ""
        Write-Host "================================================"
        Write-Host " DRY RUN PASSED"
        Write-Host "================================================"
        Write-Host "No files were modified, copied or deleted."
        Write-Host ""
        Write-Host "Detected target:"
        Write-Host "  UE $TargetSemVer / CL $($Target.CL)"
        Write-Host ""
        Write-Host "To apply the workaround:"
        Write-Host ""
        Write-Host 'Change: $ApplyChanges = $false'
        Write-Host 'To:     $ApplyChanges = $true'
        Write-Host ""
        Write-Host "Then run THIS SAME script again while the"
        Write-Host "Launcher still shows the failed Resume state."
        Write-Host "================================================"

        return
    }


    # ============================================================
    # APPLY MODE - CREATE BACKUP FIRST
    # ============================================================

    Write-Host ""
    Write-Host "================================================"
    Write-Host " APPLY MODE - CREATING BACKUP"
    Write-Host "================================================"


    $Desktop =
        [Environment]::GetFolderPath(
            [Environment+SpecialFolder]::Desktop
        )


    $Stamp =
        Get-Date -Format "yyyyMMdd_HHmmss"


    $BackupDir =
        Join-Path `
            $Desktop `
            (
                "UE58_ManifestFix_{0}_{1}" -f `
                $TargetSemVer.ToString(),
                $Stamp
            )


    New-Item `
        -Path $BackupDir `
        -ItemType Directory |
        Out-Null


    Copy-Item `
        -LiteralPath $MainItemPath `
        -Destination (Join-Path $BackupDir "installed.item")


    Copy-Item `
        -LiteralPath $PendingItemPath `
        -Destination (Join-Path $BackupDir "pending.item")


    Copy-Item `
        -LiteralPath $Main.CompleteManifestPath `
        -Destination (Join-Path $BackupDir "installed.manifest")


    Copy-Item `
        -LiteralPath $PendingManifestPath `
        -Destination (Join-Path $BackupDir "pending.manifest")


    Copy-Item `
        -LiteralPath $LauncherDat `
        -Destination (Join-Path $BackupDir "LauncherInstalled.dat")


    Copy-Item `
        -LiteralPath $BuildVersionPath `
        -Destination (Join-Path $BackupDir "Build.version")


    Write-Host ""
    Write-Host "BACKUP CREATED:"
    Write-Host $BackupDir


    # ============================================================
    # USER CONFIRMATION / CLOSE LAUNCHER
    # ============================================================

    Write-Host ""
    Write-Host "Now completely EXIT Epic Games Launcher,"
    Write-Host "including the system tray icon."
    Write-Host ""
    Write-Host "The Pending files may disappear when the"
    Write-Host "Launcher exits. That is OK because they are"
    Write-Host "already preserved in the backup."
    Write-Host ""


    $Confirm =
        Read-Host "After Launcher is fully closed, type APPLY"


    if ($Confirm -cne "APPLY") {

        Write-Host ""
        Write-Host "Cancelled."
        Write-Host "No Launcher metadata was modified."
        Write-Host ""
        Write-Host "Backup was kept:"
        Write-Host $BackupDir

        return
    }


    # ============================================================
    # VERIFY LAUNCHER IS CLOSED
    # ============================================================

    $Running =
        Get-Process `
            EpicGamesLauncher,
            EpicWebHelper `
            -ErrorAction SilentlyContinue


    if ($Running) {
        throw "STOP: Epic Games Launcher or EpicWebHelper is still running. No metadata commit was performed."
    }


    # ============================================================
    # RE-VALIDATE PHYSICAL ENGINE AFTER LAUNCHER SHUTDOWN
    # ============================================================

    $PostBuild =
        Read-JsonFile $BuildVersionPath


    if (
        $PostBuild.MajorVersion -ne $Target.Major -or
        $PostBuild.MinorVersion -ne $Target.Minor -or
        $PostBuild.PatchVersion -ne $Target.Patch -or
        [int64]$PostBuild.Changelist -ne $Target.CL
    ) {
        throw "STOP: Physical Engine changed after backup. No commit performed."
    }


    # ============================================================
    # RE-READ BACKUP SOURCES
    # ============================================================

    $BackupMain =
        Read-JsonFile `
            (Join-Path $BackupDir "installed.item")


    $BackupPending =
        Read-JsonFile `
            (Join-Path $BackupDir "pending.item")


    if ($BackupPending.AppVersionString -ne $Pending.AppVersionString) {
        throw "STOP: Backup Pending version does not match detected target."
    }


    if ($BackupPending.PrereqSHA1Hash -ne $Pending.PrereqSHA1Hash) {
        throw "STOP: Backup Pending PrereqSHA1Hash mismatch."
    }


    # ============================================================
    # 12. PROMOTE PENDING MANIFEST
    # ============================================================

    $BackupPendingManifest =
        Join-Path $BackupDir "pending.manifest"


    $BackupPendingHash =
        (Get-FileHash `
            -LiteralPath $BackupPendingManifest `
            -Algorithm SHA256).Hash


    if ($BackupPendingHash -ne $PendingManifestHash) {
        throw "STOP: Pending manifest backup hash mismatch."
    }


    Copy-Item `
        -LiteralPath $BackupPendingManifest `
        -Destination $BackupMain.CompleteManifestPath `
        -Force


    # ============================================================
    # 13. COMMIT INSTALLED ITEM METADATA
    # ============================================================

    #
    # Keep the installed item's structure/options.
    # Promote only fields known to belong to the completed build.
    #

    $BackupMain.AppVersionString =
        $BackupPending.AppVersionString

    $BackupMain.PrereqSHA1Hash =
        $BackupPending.PrereqSHA1Hash

    $BackupMain.bIsIncompleteInstall =
        $false


    $Utf8NoBom =
        New-Object System.Text.UTF8Encoding($false)


    [IO.File]::WriteAllText(
        $MainItemPath,
        ($BackupMain | ConvertTo-Json -Depth 20),
        $Utf8NoBom
    )


    # ============================================================
    # 14. UPDATE LauncherInstalled.dat
    # ============================================================

    #
    # Read the current file after Launcher shutdown so unrelated
    # application entries are preserved.
    #

    $CurrentLauncher =
        Read-JsonFile $LauncherDat


    $CurrentEntries = @(
        $CurrentLauncher.InstallationList |
        Where-Object {
            $_.AppName -eq $ExpectedAppName
        }
    )


    if ($CurrentEntries.Count -ne 1) {
        throw "STOP: UE_5.8 could not be uniquely resolved in LauncherInstalled.dat."
    }


    $CurrentEntries[0].AppVersion =
        $BackupPending.AppVersionString


    [IO.File]::WriteAllText(
        $LauncherDat,
        ($CurrentLauncher | ConvertTo-Json -Depth 20),
        $Utf8NoBom
    )


    # ============================================================
    # 15. REMOVE ONLY THIS UE_5.8 PENDING TRANSACTION
    # ============================================================

    if (Test-Path -LiteralPath $PendingItemPath) {
        Remove-Item `
            -LiteralPath $PendingItemPath
    }


    if (Test-Path -LiteralPath $PendingManifestPath) {
        Remove-Item `
            -LiteralPath $PendingManifestPath
    }


    # ============================================================
    # 16. FINAL VERIFICATION
    # ============================================================

    $FinalMain =
        Read-JsonFile $MainItemPath


    $FinalLauncher =
        Read-JsonFile $LauncherDat


    $FinalEntries = @(
        $FinalLauncher.InstallationList |
        Where-Object {
            $_.AppName -eq $ExpectedAppName
        }
    )


    if ($FinalMain.AppVersionString -ne $BackupPending.AppVersionString) {
        throw "FINAL VERIFY FAILED: installed AppVersionString mismatch."
    }


    if ($FinalMain.bIsIncompleteInstall -ne $false) {
        throw "FINAL VERIFY FAILED: installed item remains incomplete."
    }


    if ($FinalMain.PrereqSHA1Hash -ne $BackupPending.PrereqSHA1Hash) {
        throw "FINAL VERIFY FAILED: PrereqSHA1Hash mismatch."
    }


    if (
        $FinalEntries.Count -ne 1 -or
        $FinalEntries[0].AppVersion -ne $BackupPending.AppVersionString
    ) {
        throw "FINAL VERIFY FAILED: LauncherInstalled.dat mismatch."
    }


    $FinalInstalledManifestHash =
        (Get-FileHash `
            -LiteralPath $FinalMain.CompleteManifestPath `
            -Algorithm SHA256).Hash


    if ($FinalInstalledManifestHash -ne $BackupPendingHash) {
        throw "FINAL VERIFY FAILED: installed manifest does not match the Pending target manifest."
    }


    if (Test-Path -LiteralPath $PendingItemPath) {
        throw "FINAL VERIFY FAILED: Pending item still exists."
    }


    if (Test-Path -LiteralPath $PendingManifestPath) {
        throw "FINAL VERIFY FAILED: Pending manifest still exists."
    }


    Write-Host ""
    Write-Host "================================================"
    Write-Host " WORKAROUND COMPLETED SUCCESSFULLY"
    Write-Host "================================================"
    Write-Host ""
    Write-Host "Committed Engine:"
    Write-Host "  UE $TargetSemVer / CL $($Target.CL)"
    Write-Host ""
    Write-Host "Installed metadata:"
    Write-Host "  $($FinalMain.AppVersionString)"
    Write-Host ""
    Write-Host "Incomplete:"
    Write-Host "  $($FinalMain.bIsIncompleteInstall)"
    Write-Host ""
    Write-Host "LauncherInstalled.dat:"
    Write-Host "  $($FinalEntries[0].AppVersion)"
    Write-Host ""
    Write-Host "Installed manifest SHA256:"
    Write-Host "  $FinalInstalledManifestHash"
    Write-Host ""
    Write-Host "Target manifest SHA256:"
    Write-Host "  $BackupPendingHash"
    Write-Host ""
    Write-Host "Pending item exists:"
    Write-Host "  $(Test-Path $PendingItemPath)"
    Write-Host ""
    Write-Host "Pending manifest exists:"
    Write-Host "  $(Test-Path $PendingManifestPath)"
    Write-Host ""
    Write-Host "Backup:"
    Write-Host "  $BackupDir"
    Write-Host ""
    Write-Host "You can now start Epic Games Launcher."
    Write-Host "================================================"
}

3 Likes

UE-398557 has been ‘Closed’ as a duplicate of an existing known issue.

Hi @Flak,
Bug-Reporter has now marked UE-398557 as “Closed” because it is a duplicate of an existing known issue.
Could you please share the ID or public Issues Tracker link for the parent/original issue?
I’d like to reference the correct ticket in this thread and track the actual fix/status.
Thanks!

this engine is “industry standard”… ? what a sad industry

I have the same issue trying to update from UE 5.8.2 to 5.8.3

The difference is, Epic Downloader will download about 5GB of data every time I “Resume” the operation (of updating UE 5.8.2)

It ultimately remains stuck at “Resume” in Epic Launcher.

Sometimes I can then Launch UE, but my roster of project templates has disappeared and I can only start a blank project.

I checked the UE program files, and indeed the files are at 5.8.3. in fact Engine/Build/Build.version reads as: {“MajorVersion”: 5,“MinorVersion”: 8,“PatchVersion”: 3,“Changelist”: 58210709,“CompatibleChangelist”: 55116800,“IsLicenseeVersion”: 0,“IsPromotedBuild”: 1,“BranchName”: “++UE5+Release-5.8”}

I tried several times the Resume action. Next I will try to uninstall UE 5.8.2 and reinstall.

Hi @HYP_mli,

based on what you posted, I would not uninstall/reinstall UE 5.8 yet.

Your Engine/Build/Build.version already reports:

UE 5.8.3
CL 58210709

so the physical Engine files appear to have already been updated successfully.

That is the same pattern I reproduced:

Physical Engine:    UE 5.8.3
Launcher metadata:  previous version
Launcher state:     Resume

In other words, the Engine itself is already updated, but Epic Games Launcher appears to be stuck during the final manifest / metadata commit.

A reinstall may therefore be unnecessary and could simply recreate the same Launcher-side problem.

Before uninstalling anything, I would suggest running the v2.0 PowerShell diagnostic I posted above with:

$ApplyChanges = $false

This is the default read-only DRY-RUN mode.

It does not modify, delete or replace any files.

If your installation matches the same issue, it should report something similar to:

STATUS: AFFECTED / CONDITIONS MATCH

Target verification:
MATCH

In-memory commit simulation:
PASSED

DRY RUN PASSED

If you get that result, then your installation matches the same manifest-commit issue.

Only after that, if you want to apply the workaround, you can change:

$ApplyChanges = $false

to:

$ApplyChanges = $true

The Apply mode creates a complete backup before changing anything and requires explicit confirmation by typing:

APPLY

I tested v2.0 end-to-end on a real UE 5.8.2 → 5.8.3 failure.

After the workaround, Epic Games Launcher immediately changed from:

UE 5.8.2
Resume

to:

UE 5.8.3
Launch

without downloading the Engine again.

I would recommend running the DRY-RUN before uninstalling, because the current Pending transaction is useful for diagnosing and repairing this exact state.

The missing project templates may also be another symptom of the Launcher being left in an incomplete/stale application state, although I cannot confirm yet that it has exactly the same root cause.

Yes, you were right. The uninstall/reinstall didn’t help at all. I ended up using your PowerShell script which solved the issue. Many thanks!

Glad it worked for you, and thanks for confirming it.

Your result is actually very useful because it confirms that reinstalling the Engine does not necessarily fix the problem, while the manifest-state workaround does.

Hopefully this helps Epic narrow down the root cause as well.

Thanks for the detailed investigation and workaround. I encountered a very similar issue with a fresh installation of UE 5.8.3, but with one important difference.

Using Epic Games Launcher 20.3.5 on Windows 11, installation reached 100%, then failed with IS-EO-ih_early_exit. The Launcher remained stuck on Resume. Uninstalling and reinstalling didn’t help.

After digging through the logs with ChatGPT:

  • BuildPatch successfully installed and verified all 250,504 files (ProcessSuccess: TRUE, ErrorCode: OK).

  • Immediately afterward, InstallHelper stalled for approximately 30 seconds (HB-Timeout, step=RunBps).

  • UE 5.8.3 / CL 58210709 was physically installed and could launch directly through UnrealEditor.exe.

  • Unlike your update scenario, there was no completed UE 5.8 .item or LauncherInstalled.dat registration. Only pending installation records existed, with the .egi state marked Incomplete.

Your v2 workaround helped identify the problem, but it expects an existing installation record, which my fresh installation didn’t have.

I had ChatGPT build a modified PowerShell repair script that promoted the pending manifest, finalized the .item and .egi records, and registered UE 5.8.3 in LauncherInstalled.dat.

This modified script worked. My Epic Games Launcher now recognizes UE 5.8.3 and launches the editor normally, without downloading the engine again.

I’ve also prepared a generalized version specifically for this fresh-install-fail scenario:

Powershell Repair Script and README

This script automatically discovers the installation ID, build, and paths. It runs read-only by default, with safety checks, backups, and explicit confirmation before applying changes.

Important: I have only tested my installation-specific repair script. The above linked generalized script hasn’t yet been tested at all. It was built by ChatGPT based off the successful installation-specific repair script. The above linked script should be considered an untested experimental workaround and isn’t intended for existing-installation updates.

Hopefully this provides another useful data point for Epic’s investigation. Thanks again for the groundwork.

Epic Games Launcher 20.3.5 recovery test + ProcMon analysis

After updating Epic Games Launcher to 20.3.5, I performed another controlled test.

This time I restored the exact metadata/manifest state captured from my original UE 5.8.2 → 5.8.3 failure, where the physical Engine files had already been successfully updated to 5.8.3, but the Launcher transaction had not been committed correctly.

Important test limitation

This was not a fresh 5.8.2 → 5.8.3 download/update.

The physical Engine installation was already:

UE 5.8.3
CL 58210709

I restored only the previously captured Launcher/manifest transaction state in order to test how Launcher 20.3.5 recovers from the exact historical failure state.

So this test does not yet prove that the original update bug is fully fixed during an actual future hotfix update.


Restored historical broken state

Before starting Launcher 20.3.5:

Physical Engine:
    UE 5.8.3 / CL58210709

installed.item:
    5.8.2-56702186+++UE5+Release-5.8-Windows
    bIsIncompleteInstall = False

pending.item:
    5.8.3-58210709+++UE5+Release-5.8-Windows
    bIsIncompleteInstall = True

installed.manifest SHA256:
    9CB3C546C7D3C8C111D6D8AD69FE090714F5304FF1F81E099BD95B9F7493C86D

pending.manifest SHA256:
    65619BCDBC675EC4CE4C9D349B7CAAA7DA3F281A2085A2D0070533C0893BD06A

LauncherInstalled.dat:
    5.8.2-56702186+++UE5+Release-5.8-Windows

This reproduces the transaction state that previously resulted in Resume.


What Launcher 20.3.5 did

After the first startup, Launcher 20.3.5 did not show Resume.

Instead, the UI showed:

UE 5.8.3
Launch

The installed .item was rebuilt/promoted to:

AppVersionString:
    5.8.3-58210709+++UE5+Release-5.8-Windows

bIsIncompleteInstall:
    False

PrereqSHA1Hash:
    932A2A14C03E1FDA5B9FBF8200290E8FE9CC9F1A

The previous pending.item was removed.

Several properties in the new installed .item matched the historical pending.item, including:

ManifestHash
InstallTags
MainGameAppName
MainGameCatalogItemId
MainGameCatalogNamespace
BaseURLs

For example:

pending.item ManifestHash:
    6edc11fbb1bfac1c45580b1e0d9dee50f8c8b827

new installed.item ManifestHash:
    6edc11fbb1bfac1c45580b1e0d9dee50f8c8b827

This strongly suggests that Launcher 20.3.5 now performs an item-level recovery/promotion from the incomplete pending state.


However, the manifest transaction was still not completed

After the first recovery stage:

installed.item:
    5.8.3 / incomplete=False       OK

pending.item:
    removed                        OK

Launcher UI:
    5.8.3 / Launch                 OK

but the underlying manifest storage was still:

installed.manifest:
    old 5.8.2 manifest
    SHA256 = 9CB3C546C7D3C8C111D6D8AD69FE090714F5304FF1F81E099BD95B9F7493C86D

pending.manifest:
    still present
    SHA256 = 65619BCDBC675EC4CE4C9D349B7CAAA7DA3F281A2085A2D0070533C0893BD06A

Initially, LauncherInstalled.dat also remained at 5.8.2.

On a subsequent Launcher startup it was updated to:

LauncherInstalled.dat:
    5.8.3-58210709+++UE5+Release-5.8-Windows

but the manifest files still remained unchanged.

I repeated the startup again.

After Startup #3:

installed.item        = 5.8.3 / incomplete=False
pending.item          = missing
LauncherInstalled.dat = 5.8.3

installed.manifest    = old 5.8.2 manifest
pending.manifest      = still present 5.8.3 manifest

So the remaining manifest state was stable across additional Launcher restarts.


Process Monitor result

I captured Startup #3 using Sysinternals Process Monitor.

This is the most interesting part of the test.

For the installed manifest:

G:\Epic_Games\UE_5.8\.egstore\
D1AC6C594CBE88D6B55411CFA033E4CE.manifest

Launcher opened and read the existing old manifest successfully:

16:01:07.529  CreateFile  Generic Read    SUCCESS
16:01:07.536  ReadFile    36,373,780 B    SUCCESS
16:01:07.552  CloseFile                  SUCCESS

However, during the entire captured startup there were zero accesses to:

G:\Epic_Games\UE_5.8\.egstore\Pending\
D1AC6C594CBE88D6B55411CFA033E4CE.manifest

No operations of the following types were observed against the pending manifest:

CreateFile
WriteFile
SetRenameInformationFile
SetDispositionInformationFile

In other words, Launcher did not attempt to promote the pending manifest at all during this recovery startup.

There were also no relevant filesystem errors such as:

ACCESS DENIED
SHARING VIOLATION
PATH NOT FOUND
NAME NOT FOUND

All file operations for the UE 5.8 manifest GUID that were present in the captured trace completed with SUCCESS.

So at least in this recovery path, this does not look like Windows refusing a manifest rename/write operation.

Instead, Launcher appears not to enter the code path that would complete the pending-manifest promotion.


The .item is still actively rewritten

ProcMon shows that Launcher 20.3.5 actively rewrites the installed .item:

16:01:04.713  ReadFile
16:01:08.021  CreateFile / OverwriteIf   SUCCESS
16:01:08.021  WriteFile  2,665 B         SUCCESS
16:01:08.021  CloseFile                  SUCCESS

LauncherInstalled.dat was also successfully rewritten:

16:01:04.808  CreateFile / OverwriteIf   SUCCESS
16:01:04.809  WriteFile  7,062 B         SUCCESS
16:01:04.809  CloseFile                  SUCCESS

So there is no evidence in this trace that file permissions were the limiting factor.


Current interpretation

Launcher 20.3.5 appears to have improved recovery from this stale transaction state:

pending.item
      ↓
installed.item 5.8.3
bIsIncompleteInstall=False
      ↓
pending.item removed
      ↓
LauncherInstalled.dat eventually updated to 5.8.3
      ↓
UI shows Launch

But the final manifest transaction remains incomplete:

installed.manifest = old 5.8.2 manifest
pending.manifest   = new 5.8.3 manifest

On later startups Launcher reads the old installed manifest while apparently ignoring the still-existing pending manifest.

So my current conclusion is:

Epic Games Launcher 20.3.5 improves recovery of the visible/install-metadata state, but in this controlled replay it still does not complete the pending-manifest promotion.

This is important because the UI can now show 5.8.3 / Launch even while the underlying manifest storage remains internally inconsistent.

It also suggests that the original issue is probably not simply a filesystem permission or file-locking problem.

At least in this reproduced recovery state, the remaining pending manifest does not appear to be blocked during promotion — no promotion attempt is visible in the captured trace at all.


Final verification

After completing the test, I restored the known-good state:

installed.item:
    5.8.3-58210709+++UE5+Release-5.8-Windows
    bIsIncompleteInstall = False

installed.manifest SHA256:
    65619BCDBC675EC4CE4C9D349B7CAAA7DA3F281A2085A2D0070533C0893BD06A

pending.item:
    absent

pending.manifest:
    absent

LauncherInstalled.dat:
    5.8.3-58210709+++UE5+Release-5.8-Windows

Physical Engine:
    UE 5.8.3 / CL58210709

I then launched UE 5.8.3 normally and confirmed that the Engine starts correctly.

So the physical Engine installation itself remains valid.


Current recommendation

If Epic Games Launcher 20.3.5 completes a UE 5.8.x update normally, does not fall back into an Update → Resume loop, the Engine launches normally, and the state remains stable across subsequent Launcher restarts, no workaround should normally be necessary.

The v2.0 workaround should only be considered if the original symptoms return, for example:

  • the update finishes but the Launcher remains on Resume
  • the Launcher repeatedly offers Update
  • the physical Engine files are already on the target version, but the Launcher still reports an older/incomplete state

In that situation, the v2.0 script can first be run in its default read-only DRY-RUN mode to determine whether the installation matches the same manifest-commit failure before making any changes.

A full uninstall/reinstall should not be the first troubleshooting step, since another affected user already confirmed that reinstalling did not resolve the issue, while the manifest-state workaround did.

The definitive test will be the next real UE 5.8.x hotfix update under Launcher 20.3.5.

That will determine whether the original failure in the actual update/commit path has been fixed, or whether Launcher 20.3.5 has only improved recovery from an already broken transaction state.

Thanks, Kyle — this is a very useful additional data point.

The distinction you found is especially interesting because your failure happens during a fresh UE 5.8.3 installation, while my reproduced cases were updates of an already registered UE 5.8 installation.

In my case, BuildPatch also completed successfully and the physical Engine was already valid, but an older installed .item, manifest and LauncherInstalled.dat entry still existed.

Your case appears to fail one stage earlier:

BuildPatch succeeds
        ↓
physical UE 5.8.3 installation is valid
        ↓
InstallHelper / post-install finalization fails
        ↓
only pending records remain
        ↓
no completed installed registration
        ↓
Launcher stays on Resume
1 Like

Controlled fresh-install comparison with Kyle G’s report

After Kyle G reported a fresh UE 5.8.3 installation failing at 100% with:

IS-EO-ih_early_exit

followed by the Launcher getting stuck on Resume, I performed a controlled fresh-install test on my own system using Epic Games Launcher 20.3.5.

Before starting the test, I removed all known UE 5.8 installation registration state while preserving my existing working Engine installation separately.

An important detail discovered during this preparation was that Epic also keeps installation state here:

C:\ProgramData\Epic\EpicOnlineServicesShared\InstallHelper\InstalledItems\

The old UE 5.8 installation still had:

D1AC6C594CBE88D6B55411CFA033E4CE.egi

with:

state = Installed

and:

dir = G:\Epic_Games\UE_5.8

Even after the normal .item record and the UE 5.8 entry in LauncherInstalled.dat had been removed, this .egi record caused the Launcher to reconstruct a new .item and display Repair instead of Install.

ProcMon showed the sequence clearly:

EpicOnlineServicesInstallHelper.exe
reads the existing .egi

→

EpicGamesLauncher.exe
does not find the normal .item

→

the Launcher creates a reconstructed .item

→

the Launcher repeatedly checks the old:

G:\Epic_Games\UE_5.8\.egstore\...manifest

which no longer exists

→

the UI shows Repair

After moving both the old .egi and the reconstructed .item out of the live state, with no UE 5.8 entry in LauncherInstalled.dat and no Engine present at the old install path, the Launcher finally showed:

Not Installed

and:

Install

This gave me a genuine fresh-install baseline.

I then installed UE 5.8.3 to a new location on another drive:

H:\Epic_Games\UE_5.8_FreshTest\UE_5.8

using the same component selection I normally use:

  • Core Components
  • Templates and Feature Packs
  • Engine Source

The fresh installation completed normally.

Final result:

100% → Launch

There was no:

IS-EO-ih_early_exit

and no:

Resume

The Engine also launched successfully afterwards.

The new installation received a new installation ID:

AE781EAC3329F9BD72C636D27920C5D

and the final physical state was consistent:

UE 5.8.3-58210709+++UE5+Release-5.8-Windows

Build.version: 5.8.3

Changelist: 58210709

Installed manifest:

AE781EAC3329F9BD72C636D27920C5D.manifest

SHA256:

65619BCDBC675EC4CE4C9D349B7CAAA7DA3F281A2085A2D0070533C0893BD06A

No pending manifest remained.

The .egi state was:

Installed

and the .item had:

bIsIncompleteInstall = False

After restarting the Launcher, the UE 5.8 entry was also added to LauncherInstalled.dat, and the installation remained stable.

So, unlike Kyle G’s fresh-install case, I was not able to reproduce the IS-EO-ih_early_exit → Resume failure on Launcher 20.3.5.

This suggests that the fresh-install failure is not deterministic for every UE 5.8.3 installation under Launcher 20.3.5 and may depend on additional machine-specific or installation-state conditions.

It also shows that .egi records under EpicOnlineServicesShared\InstallHelper\InstalledItems are an important part of the Launcher’s persistent installation state and can cause an apparently removed Engine installation to be reconstructed as Repair.

1 Like