Skip to content

[Bug] Windows installer 2.0.290 fails with error 1603 during ValidateInstallRootPreview #701

Open

Description

@VirtualGIT20

Bug Symptoms

Bug description

I'm experiencing an installation failure with Vibepollo 2.0.290 on Windows.

When attempting to reinstall Vibepollo, the installer successfully removes the existing installation but then fails with MSI error 1603.

The installation is blocked during the "ValidateInstallRootPreview" custom action.

Steps to reproduce

  1. Start with Vibepollo installed in "C:\Program Files\Apollo".
  2. Run the Windows installer to reinstall/update Vibepollo.
  3. The existing installation is removed successfully (exit code 0).
  4. The new installation fails during directory validation.

Actual behavior

The installer returns:

The install folder or an existing product directory is unsafe,
writable by an untrusted account, or contains a reparse point.
Close the host and run the bootstrapper from an elevated account.

CustomAction ValidateInstallRootPreview returned actual error code 1603
Action ended: ValidateInstallRootPreview. Return value 3.

However, the MSI log confirms:

MsiRunningElevated = 1
Privileged = 1
AdminUser = 1

Additional information

  • Installer version: 2.0.290
  • Platform: Windows x64
  • Installation directory: "C:\Program Files\Apollo"
  • Failure date: November 1, 2026
  • MSI error code: 1603
  • The previous version was successfully removed (exit code 0).
  • Previous installations of version 2.0.290 succeeded on October 25 and October 26.
  • The latest MSI log also reports "MsiSystemRebootPending = 1".

Could you help identify what causes "ValidateInstallRootPreview" to reject the installation directory even when the installer is running with elevated privileges?

Is there a safe way to determine the specific directory or permission that is triggering this validation?

I can provide the full installation logs if additional information is needed.

Expected Behavior

The installer should complete successfully, or provide a specific explanation identifying which directory, permission, or reparse point is causing the security validation to fail.

Ideally, the existing installation should not be removed before this validation succeeds.

Windows Version

25H2

Package

Windows - exe installer

GPU Type

NVIDIA

GPU Model

5070

GPU Driver Version

latest

Capture Method

None

Apps

Logs (Optional but Recommended)

vibepollo-issue-logs-redacted-20261101.txt

Screenshot (Optional)


Activity

  1. markmghali commented on Nov 1, 2026

    @markmghali

    same issue

    Image
  2. jcbrizzy commented on Nov 1, 2026

    @jcbrizzy

    Getting something similar w/ 2.0.3 ..... awesome. Uninstalled everything.. and won't install.

  3. Nonary commented on Nov 1, 2026

    @Nonary
    Owner

    We are comparing this failure across Vibeshine #391, Vibeshine #392, and Vibepollo #701. The current installer log does not identify the rejected path or Windows error. This read-only diagnostic collects the missing details automatically.

    Run once and attach one report

    1. Open Windows PowerShell as administrator from the Start menu.
    2. Copy and paste this entire command, then press Enter. It downloads the diagnostic embedded in this comment, verifies its SHA-256 checksum, and runs it. There is no need to save a script manually or change your system's execution-policy setting.
    & { $ErrorActionPreference='Stop'; try { $c=Invoke-RestMethod -Uri 'https://api.github.com/repos/Nonary/Vibepollo/issues/comments/6561597946' -Headers @{'User-Agent'='InstallerFolderDiagnostic'}; $m=[regex]::Match($c.body,'(?s)<!-- installer-diagnostic-v2 -->\s*```powershell\r?\n(.*?)\r?\n```'); if(-not $m.Success){throw 'Diagnostic script was not found in the issue comment.'}; $s=$m.Groups[1].Value.Replace("`r",'').Trim(); $h=[Security.Cryptography.SHA256]::Create(); $hash=[BitConverter]::ToString($h.ComputeHash([Text.Encoding]::UTF8.GetBytes($s))).Replace('-','').ToLowerInvariant(); $h.Dispose(); if($hash -ne 'f5219668a649988a598d600b8a0c4d3b7646a9e4e5fdb5da759122699c86d4b2'){throw 'Diagnostic script checksum mismatch. Please report this instead of running it.'}; $p=Join-Path $env:TEMP ('installer-folder-diagnostic-'+[guid]::NewGuid().ToString('N')+'.ps1'); [IO.File]::WriteAllText($p,$s,(New-Object Text.UTF8Encoding($false))); & "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" -NoLogo -NoProfile -ExecutionPolicy Bypass -File $p } catch { Write-Host $_ -ForegroundColor Red } }
    1. When it finishes, File Explorer opens with the report selected. Drag that text file into a reply here. If Explorer cannot open, the report's full path is printed in PowerShell. If the command fails, paste the displayed error instead.

    The collector automatically checks the normal installation locations plus locations found in relevant installer registrations. It records ancestor and installation-file ownership/permissions, raw security descriptors, reparse points, native file-open/security-query errors, MSI product/directory identities, Windows build, elevation, and reboot markers. Missing installation folders are recorded too. No separate screenshots, registry exports, or commands are needed for the initial collection.

    It does not change permissions, uninstall anything, stop/start services, execute installed application code, or read configuration/credential file contents. It writes the diagnostic script, its text report, and temporary compiler files; it opens File Explorer at the end. It may take a few minutes for a large installation. The report contains paths/account SIDs, so review or redact identifying details before uploading it. The report is never uploaded automatically.

    Validation so far: PowerShell syntax, embedded C# compilation, and mocked permission-classification checks passed. The native Windows probes still need an affected Windows machine; the collector records probe failures in the report. This gathers the evidence needed to distinguish an unsafe directory from a guard compatibility problem; it does not assume either outcome or guarantee a fix from one report.

    Diagnostic source (automatically downloaded by the command above)
    # Windows PowerShell 5.1+. Read-only except for the report and compiler temporary files.
    # Does not start/stop services, change ACLs, or read file contents.
    [CmdletBinding()]
    param(
        [string[]]$InstallRoot = @(),
        [ValidateRange(1,100000)][int]$MaxEntries = 20000
    )
    $ErrorActionPreference = 'Stop'
    $report = Join-Path $env:TEMP ('installer-folder-diagnostic-{0}.txt' -f (Get-Date -Format 'yyyyMMdd-HHmmss'))
    $lines = New-Object 'System.Collections.Generic.List[string]'
    function Log([string]$Text) { $lines.Add($Text) }
    $identity = [Security.Principal.WindowsIdentity]::GetCurrent()
    $principal = New-Object Security.Principal.WindowsPrincipal($identity)
    Log 'Vibeshine / Vibepollo installer folder diagnostic v2'
    Log ('Time UTC: ' + [DateTime]::UtcNow.ToString('o'))
    Log ('Elevated: ' + $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))
    Log ('PowerShell: ' + $PSVersionTable.PSVersion.ToString())
    Log ('OS: ' + [Environment]::OSVersion.VersionString)
    Log ('64-bit PowerShell: ' + [Environment]::Is64BitProcess)
    Log ('Process user SID: ' + $identity.User.Value)
    Log ('ProgramFiles environment: ' + $env:ProgramFiles)
    Log ('ProgramW6432 environment: ' + $env:ProgramW6432)
    Log ('ProgramFiles(x86) environment: ' + ${env:ProgramFiles(x86)})
    Log 'Read-only inspection; no file contents collected. Paths and account SIDs may identify users.'
    Log 'The preview-open probe closes each handle immediately; this is not a full reproduction of the MSI guard.'
    
    # Match the native guard's preview access/share flags, without following a
    # final-component reparse point and without creating or modifying any object.
    try {
        if (-not ('InstallerFolderDiagnostic.Native' -as [type])) {
            Add-Type -TypeDefinition @'
    using System;
    using System.Runtime.InteropServices;
    using System.Text;
    using System.Collections.Generic;
    namespace InstallerFolderDiagnostic {
        public class ProbeResult {
            public int OpenError;
            public uint SecurityError;
            public int DescriptorError;
            public string Sddl;
        }
        public static class Native {
            [DllImport("kernel32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
            private static extern IntPtr CreateFileW(string path, uint access,
                uint share, IntPtr security, uint disposition, uint flags, IntPtr template);
            [DllImport("kernel32.dll", SetLastError=true)]
            private static extern bool CloseHandle(IntPtr handle);
            [DllImport("advapi32.dll", SetLastError=true)]
            private static extern uint GetSecurityInfo(IntPtr handle, int objectType,
                uint information, out IntPtr owner, out IntPtr group, out IntPtr dacl,
                out IntPtr sacl, out IntPtr descriptor);
            [DllImport("advapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)]
            private static extern bool ConvertSecurityDescriptorToStringSecurityDescriptorW(
                IntPtr descriptor, uint revision, uint information, out IntPtr text, out uint length);
            [DllImport("kernel32.dll")]
            private static extern IntPtr LocalFree(IntPtr memory);
            [DllImport("msi.dll", CharSet=CharSet.Unicode)]
            private static extern uint MsiEnumRelatedProductsW(string upgrade, uint reserved, uint index, StringBuilder code);
            [DllImport("msi.dll", CharSet=CharSet.Unicode)]
            private static extern uint MsiGetProductInfoExW(string code, string sid, uint context, string property, StringBuilder value, ref uint length);
            [DllImport("msi.dll", CharSet=CharSet.Unicode)]
            private static extern int MsiGetComponentPathExW(string product, string component, string sid, uint context, StringBuilder value, ref uint length);
            public static string[] RelatedProducts(string upgrade) {
                List<string> codes = new List<string>();
                for (uint i=0; i<4096; i++) {
                    StringBuilder code = new StringBuilder(39);
                    uint result = MsiEnumRelatedProductsW(upgrade, 0, i, code);
                    if (result == 259) return codes.ToArray();
                    if (result != 0) throw new System.ComponentModel.Win32Exception((int)result);
                    codes.Add(code.ToString());
                }
                throw new Exception("MSI enumeration limit reached");
            }
            public static string ProductInfo(string code, string property) {
                StringBuilder value = new StringBuilder(32768); uint length=32768;
                uint result = MsiGetProductInfoExW(code, null, 4, property, value, ref length);
                if (result != 0) throw new System.ComponentModel.Win32Exception((int)result);
                return value.ToString();
            }
            public static string ComponentPath(string code, string component) {
                StringBuilder value = new StringBuilder(32768); uint length=32768;
                int state = MsiGetComponentPathExW(code, component, null, 4, value, ref length);
                return state == 3 ? value.ToString() : "<MSI component state: " + state + ">";
            }
            public static ProbeResult Preview(string path) {
                ProbeResult result = new ProbeResult();
                IntPtr h = CreateFileW(path, 0x00020100, 3, IntPtr.Zero, 3,
                    0x02200000, IntPtr.Zero);
                if (h == new IntPtr(-1)) { result.OpenError=Marshal.GetLastWin32Error(); return result; }
                IntPtr descriptor=IntPtr.Zero, text=IntPtr.Zero;
                try {
                    IntPtr owner, group, dacl, sacl;
                    result.SecurityError=GetSecurityInfo(h, 1, 5, out owner, out group, out dacl, out sacl, out descriptor);
                    if (result.SecurityError == 0) {
                        uint length;
                        if (ConvertSecurityDescriptorToStringSecurityDescriptorW(descriptor,1,5,out text,out length))
                            result.Sddl=Marshal.PtrToStringUni(text);
                        else result.DescriptorError=Marshal.GetLastWin32Error();
                    }
                    return result;
                } finally {
                    if (text != IntPtr.Zero) LocalFree(text);
                    if (descriptor != IntPtr.Zero) LocalFree(descriptor);
                    CloseHandle(h);
                }
            }
        }
    }
    '@
        }
        $nativeAvailable = $true
    } catch {
        $nativeAvailable = $false
        Log ('Native preview-open probe unavailable: ' + $_.Exception.Message)
    }
    
    $trusted = @('S-1-5-18','S-1-5-32-544','S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464')
    $roots = New-Object 'System.Collections.Generic.List[string]'
    function Add-Root([string]$Path) {
        if ([string]::IsNullOrWhiteSpace($Path)) { return }
        if ($Path -notmatch '^[a-zA-Z]:\\') { Log ('Non-local/invalid registered path (not inspected): ' + $Path); return }
        try {
            $full = [IO.Path]::GetFullPath($Path).TrimEnd('\')
            if ($full.Length -le 3) { Log ('Drive root registration (not recursively inspected): ' + $full); return }
            if (-not $roots.Contains($full)) { $roots.Add($full) }
        } catch { Log ('Invalid registered path: ' + $Path + '; ' + $_.Exception.Message) }
    }
    foreach ($root in $InstallRoot) { Add-Root $root }
    foreach ($base in @($env:ProgramW6432,$env:ProgramFiles,${env:ProgramFiles(x86)})) {
        if ($base) { foreach ($name in @('Sunshine','Apollo','Vibeshine','Vibepollo')) { Add-Root (Join-Path $base $name) } }
    }
    Log ''
    Log 'Relevant uninstall registrations (read-only; no uninstall commands executed):'
    foreach ($hive in @([Microsoft.Win32.RegistryHive]::LocalMachine,[Microsoft.Win32.RegistryHive]::CurrentUser)) {
        foreach ($view in @([Microsoft.Win32.RegistryView]::Registry64,[Microsoft.Win32.RegistryView]::Registry32)) {
            $baseKey = $null; $uninstall = $null
            try {
                $baseKey = [Microsoft.Win32.RegistryKey]::OpenBaseKey($hive,$view)
                $uninstall = $baseKey.OpenSubKey('SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall',$false)
                if ($null -eq $uninstall) { continue }
                foreach ($keyName in $uninstall.GetSubKeyNames()) {
                    $key = $null
                    try {
                        $key = $uninstall.OpenSubKey($keyName,$false)
                        if ($null -eq $key) { continue }
                        $displayName = [string]$key.GetValue('DisplayName')
                        if ($displayName -notmatch '(?i)sunshine|vibeshine|apollo|vibepollo' -and $keyName -notmatch '^(Sunshine|Vibeshine|Apollo|Vibepollo)$') { continue }
                        Log ('REGISTRY: ' + $hive + '/' + $view + '/' + $keyName)
                        foreach ($field in @('DisplayName','DisplayVersion','WindowsInstaller','ProductCode','InstallLocation')) {
                            Log ($field + ': ' + [string]$key.GetValue($field))
                            if ($null -ne $key.GetValue($field)) { Log ($field + ' registry type: ' + $key.GetValueKind($field)) }
                        }
                        Add-Root ([string]$key.GetValue('InstallLocation'))
                    } catch { Log ('Registration read error: ' + $_.Exception.Message) }
                    finally { if ($key) { $key.Dispose() } }
                }
            } catch { Log ('Registry read error: ' + $_.Exception.Message) }
            finally { if ($uninstall) { $uninstall.Dispose() }; if ($baseKey) { $baseKey.Dispose() } }
        }
    }
    if ($nativeAvailable) {
        foreach ($upgrade in @('{C2C36624-2D9C-4AFD-9C79-6B7861AE4A0D}','{E3FA501A-85F8-4187-85A7-D6E6BDC7EDA1}')) {
            try {
                $products = @([InstallerFolderDiagnostic.Native]::RelatedProducts($upgrade))
                Log ('MSI upgrade family: ' + $upgrade + '; related products: ' + $products.Count)
                foreach ($product in $products) {
                    Log ('MSI product: ' + $product)
                    foreach ($field in @('ProductName','VersionString','InstallLocation','LocalPackage')) {
                        try {
                            $value = [InstallerFolderDiagnostic.Native]::ProductInfo($product,$field)
                            Log ($field + ': ' + $value)
                            if ($field -eq 'InstallLocation') { Add-Root $value }
                        } catch { Log ($field + ' query error: ' + $_.Exception.Message) }
                    }
                    foreach ($component in @('{B6D8A6A3-63B7-4C3F-8A2C-2C8F2B2F3B61}','{640D87CF-69A4-4F54-AE29-941F78D020B2}')) {
                        try {
                            $value = [InstallerFolderDiagnostic.Native]::ComponentPath($product,$component)
                            Log ('Directory component ' + $component + ': ' + $value)
                            if ($value -notmatch '^<') { Add-Root $value }
                        } catch { Log ('Directory component query error: ' + $_.Exception.Message) }
                    }
                }
            } catch { Log ('Related MSI product query error: ' + $_.Exception.Message) }
        }
    }
    $windows = Get-ItemProperty -LiteralPath 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -ErrorAction SilentlyContinue
    if ($windows) { Log ('Windows build: {0}.{1}; display version: {2}' -f $windows.CurrentBuildNumber,$windows.UBR,$windows.DisplayVersion) }
    foreach ($pendingKey in @('HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending','HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired')) {
        Log ('Reboot marker ' + $pendingKey + ': ' + (Test-Path -LiteralPath $pendingKey))
    }
    $seen = @{}
    $script:count = 0
    $script:flagged = 0
    function Inspect-Path([string]$Path, [bool]$Strict, [bool]$AlwaysPrint) {
        if ($seen.ContainsKey($Path)) { return $seen[$Path] }
        $seen[$Path] = $null
        $script:count++
        $details = New-Object 'System.Collections.Generic.List[string]'
        $reasons = New-Object 'System.Collections.Generic.List[string]'
        $item = $null
        try {
            $item = Get-Item -LiteralPath $Path -Force -ErrorAction Stop
            $details.Add('Attributes: ' + $item.Attributes)
            if ($item.Attributes -band [IO.FileAttributes]::ReparsePoint) {
                $reasons.Add('Reparse point; descendants will not be inspected')
            }
            if ($nativeAvailable) {
                $probe = [InstallerFolderDiagnostic.Native]::Preview($Path)
                $details.Add('Native preview-open Win32 error: ' + $probe.OpenError)
                $details.Add('Native GetSecurityInfo error: ' + $probe.SecurityError)
                $details.Add('Native SDDL conversion error: ' + $probe.DescriptorError)
                $details.Add('Native owner/DACL SDDL: ' + $probe.Sddl)
                if ($probe.OpenError -ne 0) { $reasons.Add('Native preview-open failed: ' + $probe.OpenError) }
                if ($probe.SecurityError -ne 0) { $reasons.Add('Native security query failed: ' + $probe.SecurityError) }
                if ($probe.DescriptorError -ne 0) { $reasons.Add('Native SDDL conversion failed: ' + $probe.DescriptorError) }
            }
            $acl = Get-Acl -LiteralPath $Path -ErrorAction Stop
            $details.Add('SDDL: ' + $acl.Sddl)
            $owner = $acl.GetOwner([Security.Principal.SecurityIdentifier]).Value
            $details.Add('Owner SID: ' + $owner)
            $details.Add('DACL protected: ' + $acl.AreAccessRulesProtected)
            if ($trusted -notcontains $owner) { $reasons.Add('Owner is outside native guard whitelist') }
            $rules = $acl.GetAccessRules($true, $true, [Security.Principal.SecurityIdentifier])
            foreach ($rule in $rules) {
                $sid = $rule.IdentityReference.Value
                $mask = ([long]$rule.FileSystemRights) -band 4294967295L
                $inheritOnly = ($rule.PropagationFlags -band [Security.AccessControl.PropagationFlags]::InheritOnly) -ne 0
                $details.Add(('ACE: SID={0}; type={1}; mask=0x{2:X8}; inherited={3}; inheritance={4}; propagation={5}' -f $sid,$rule.AccessControlType,$mask,$rule.IsInherited,$rule.InheritanceFlags,$rule.PropagationFlags))
                if ($rule.AccessControlType -ne [Security.AccessControl.AccessControlType]::Allow) { continue }
                if (($inheritOnly -and -not $Strict) -or ($trusted -contains $sid) -or ($inheritOnly -and $sid -eq 'S-1-3-0')) { continue }
                $unsafeMask = 0x500D0040L
                if ($Strict) { $unsafeMask = $unsafeMask -bor 0x116L }
                if (($mask -band $unsafeMask) -ne 0) { $reasons.Add('Allow ACE rejected by native guard mask: ' + $sid) }
            }
        } catch {
            $reasons.Add('Inspection error: ' + $_.Exception.GetType().FullName + '; HResult=' + $_.Exception.HResult + '; ' + $_.Exception.Message)
        }
        if ($AlwaysPrint -or $reasons.Count -gt 0) {
            Log ''
            Log ('PATH: ' + $Path)
            Log ('Strict mutation check: ' + $Strict)
            foreach ($reason in $reasons) { Log ('CHECK: ' + $reason) }
            foreach ($detail in $details) { Log $detail }
        }
        if ($reasons.Count -gt 0) { $script:flagged++ }
        $seen[$Path] = $item
        return $item
    }
    
    try {
        foreach ($root in $roots) {
            $root = [IO.Path]::GetFullPath($root).TrimEnd('\')
            Log ('Requested install root: ' + $root)
            $ancestors = New-Object 'System.Collections.Generic.List[string]'
            $path = $root
            while ($path) {
                $ancestors.Insert(0,$path)
                $parent = [IO.Directory]::GetParent($path)
                if ($null -eq $parent) { break }
                $path = $parent.FullName
            }
            $rootItem = $null
            $redirected = $false
            foreach ($path in $ancestors) {
                $item = Inspect-Path $path ($path.Length -gt 3) $true
                if ($null -ne $item -and ($item.Attributes -band [IO.FileAttributes]::ReparsePoint)) { $redirected = $true; break }
                if ($path -eq $root) { $rootItem = $item }
            }
            if ($redirected -or $null -eq $rootItem -or -not $rootItem.PSIsContainer) { continue }
            $safeToRecurse = $false
            foreach ($base in @($env:ProgramW6432,$env:ProgramFiles,${env:ProgramFiles(x86)})) {
                if ($base -and $root.StartsWith($base.TrimEnd('\') + '\',[StringComparison]::OrdinalIgnoreCase)) { $safeToRecurse = $true }
            }
            foreach ($explicitRoot in $InstallRoot) { if ($root -eq $explicitRoot.TrimEnd('\')) { $safeToRecurse = $true } }
            if (-not $safeToRecurse) { Log ('Only root/ancestors inspected outside Program Files: ' + $root); continue }
            $pending = New-Object 'System.Collections.Generic.Stack[string]'
            $pending.Push($root)
            while ($pending.Count -gt 0 -and $script:count -lt $MaxEntries) {
                Write-Progress -Activity 'Collecting installer diagnostics' -Status ('Inspected ' + $script:count + ' entries')
                $directory = $pending.Pop()
                try {
                    foreach ($child in (Get-ChildItem -LiteralPath $directory -Force -ErrorAction Stop)) {
                        if ($script:count -ge $MaxEntries) { break }
                        $item = Inspect-Path $child.FullName $true $false
                        if ($null -ne $item -and $item.PSIsContainer -and -not ($item.Attributes -band [IO.FileAttributes]::ReparsePoint)) { $pending.Push($item.FullName) }
                    }
                } catch { Log ('Enumeration error at ' + $directory + ': ' + $_.Exception.Message) }
            }
            if ($script:count -ge $MaxEntries) { Log 'SCAN LIMIT REACHED; descendant inspection is incomplete.' }
        }
    } catch { Log ('Diagnostic error: ' + $_.Exception.Message) }
    Log ''
    Log ('Inspected entries: ' + $script:count + '; entries with checks/errors: ' + $script:flagged)
    Log 'No flagged entries does not prove MSI validation will pass: races and concurrent handle pinning are not fully reproduced.'
    $lines | Set-Content -LiteralPath $report -Encoding UTF8
    Write-Progress -Activity 'Collecting installer diagnostics' -Completed
    Write-Host ('Report saved to: ' + $report)
    Write-Host 'Review paths and account SIDs before attaching the report to your issue.'
    try { Start-Process -FilePath (Join-Path $env:WINDIR 'explorer.exe') -ArgumentList ('/select,"' + $report + '"') } catch { Write-Host 'Could not open File Explorer. Use the report path above.' }
  4. emreerisen commented on Nov 1, 2026

    @emreerisen

    I ran the read-only installer folder diagnostic from an elevated PowerShell session. The installer still fails with MSI error 1603 during ValidateInstallRootPreview, with the message that the install folder or an existing product directory is unsafe, writable by an untrusted account, or contains a reparse point.

    The diagnostic results for this machine:

    • Windows 11, display version 26H2, build 26300.9818
    • Diagnostic ran elevated: True
    • Reboot-pending markers: False
    • For C:\Program Files\Apollo and its parent directories:
      • Native preview-open Win32 error: 0
      • Native GetSecurityInfo error: 0
      • Native SDDL conversion error: 0
      • Apollo directory owner: SYSTEM (S-1-5-18)
      • No suspicious ACL entries or reparse points were reported.
    • The Vibepollo uninstall registration still exists at HKLM\...\Vibepollo and points to C:\Program Files\Apollo\, with version 2.0.2-daily.d20261014.1+66e169c325da.
    • However, the MSI product identity discovered by the diagnostic is not recognized by Windows Installer as currently installed (MsiGetProductInfoEx returns “This action is only valid for products that are currently installed”).

    So far, the diagnostic does not show an obvious permissions or reparse-point problem in the Apollo install directory. The stale-looking uninstall/MSI registration may be relevant, but I cannot confirm that it is the cause.

    Could you please advise what to try next, or whether you can provide a more detailed/instrumented installer build that identifies exactly which path or validation check is causing ValidateInstallRootPreview to fail?

    I have the complete diagnostic report available and can attach/paste it if needed.

  5. blitz2kx commented on Nov 2, 2026

    @blitz2kx

    Same error - same issue. identical to what was posted.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions