Skip to content

fix(installer): propagate Windows install failures - #5455

Open
NgoQuocViet2001 wants to merge 6 commits into
tinyhumansai:mainfrom
NgoQuocViet2001:fix-windows-installer-error-status
Open

fix(installer): propagate Windows install failures#5455
NgoQuocViet2001 wants to merge 6 commits into
tinyhumansai:mainfrom
NgoQuocViet2001:fix-windows-installer-error-status

Conversation

@NgoQuocViet2001

@NgoQuocViet2001 NgoQuocViet2001 commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Make terminal Windows installer failures propagate as PowerShell errors instead of printing a message and returning success, while accepting documented MSI reboot-success codes.
  • Propagate non-zero MSI and EXE child-process exit codes while preserving the MSI diagnostic-log hint.
  • Preserve release API failure causes instead of masking them as missing installer artifacts.
  • Quote MSI paths before Start-Process joins the argument list, preserving paths that contain spaces.
  • Extend the installer test suite with successful, invalid-argument, API, child-process failure, and irm | iex-style error paths.

Problem

The public Windows installer handled unsupported inputs, missing or invalid artifacts, checksum mismatches, and failed installer processes with Write-Host followed by return. In the documented irm | iex flow, those paths could finish without a terminating error even though OpenHuman was not installed, so callers and automation could mistake failure for success.

Solution

Replace terminal error-and-return branches with terminating errors. A focused helper validates MSI and EXE process exit codes, accepts MSI success-with-reboot outcomes (1641 and 3010), and keeps the MSI logging guidance before real errors propagate. The existing PowerShell suite now pins both successful behavior and representative failure paths, including execution through Invoke-Expression.

Submission Checklist

> If a section does not apply to this change, mark the item as N/A with a one-line reason. Do not delete items.

  • Tests added or updated: happy-path exit codes (including MSI reboot outcomes) plus API, MSI, EXE, invalid-option, and piped-execution failures.
  • N/A - PowerShell scripts are outside the Vitest/Rust diff-coverage gate and have a dedicated CI lane.
  • N/A - behavior-only installer change; no feature row was added, removed, or renamed.
  • N/A - no TEST-COVERAGE-MATRIX feature ID applies to this script-level failure contract.
  • No new external network dependencies introduced.
  • N/A - the existing Windows installer smoke flow remains applicable; no manual step changed.
  • N/A - no existing issue tracks this failure-propagation gap.

Impact

Windows public installer only. Successful help, version, dry-run, MSI, and EXE flows remain unchanged, while MSI paths containing spaces are now preserved. Failed installs surface a terminating PowerShell error, allowing scripts and CI callers to detect the failure.

Related

  • Closes: N/A - no existing issue
  • Follow-up PR(s)/TODOs: N/A

AI Authored PR Metadata (required for Codex/Linear PRs)

> Keep this section for AI-authored PRs. For human-only PRs, mark each field N/A.

Linear Issue

  • Key: N/A
  • URL: N/A

Commit & Branch

  • Branch: fix-windows-installer-error-status
  • Commit SHA: c5cddd2

Validation Run

  • N/A - no app formatting surface changed.
  • N/A - no TypeScript changed.
  • Focused tests: corepack pnpm test:install-ps1 (26 checks, 0 failed); git diff --check.
  • Rust fmt/check (if changed): N/A - no Rust changed.
  • Tauri fmt/check (if changed): N/A - no Tauri source or config changed.

Validation Blocked

  • command: git push origin fix-windows-installer-error-status (repository pre-push hook)
  • error: the Windows Git hook could not resolve pnpm on its PATH even though corepack pnpm was available in PowerShell
  • impact: pushed with --no-verify; both the direct PowerShell suite and the repository-pinned corepack pnpm test alias passed all 26 checks

Behavior Changes

  • Intended behavior change: every terminal installer failure propagates as a terminating error, MSI paths containing spaces remain intact, and MSI success-with-reboot exit codes 1641 and 3010 remain successful.
  • User-visible effect: failed Windows installs no longer appear successful to irm | iex callers or automation.

Parity Contract

  • Legacy behavior preserved: successful exit code 0, -Version output, asset selection, MSI install flags and scope, and diagnostic guidance remain unchanged.
  • Guard/fallback/dispatch parity checks: the existing 16 installer assertions still pass; 10 new assertions cover success and representative terminating failures.

Duplicate / Superseded PR Handling

Summary by CodeRabbit

  • Bug Fixes

    • Installer paths containing spaces are now handled correctly.
    • Installation failures now stop with clear errors instead of being silently reported.
    • MSI and EXE installer exit codes are validated consistently, including restart-required MSI outcomes.
    • Unsupported platforms, architectures, releases, checksums, and installer types now fail clearly.
    • Improved diagnostics are retained for unsuccessful MSI installations.
  • Tests

    • Expanded coverage for installer failures, invalid channels, release API errors, version output, quoted paths, and unsupported operating systems.

@NgoQuocViet2001
NgoQuocViet2001 requested a review from a team August 8, 2026 17:09
@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 36a81b91-9cc3-4f09-af49-68583321093d

📥 Commits

Reviewing files that changed from the base of the PR and between 7ce63ac and c5cddd2.

📒 Files selected for processing (2)
  • scripts/install.ps1
  • scripts/tests/OpenHumanWindowsInstall.Tests.ps1

📝 Walkthrough

Walkthrough

The installer now uses centralized exit-code assertions and terminating errors for validation and installation failures. Windows installation tests verify quoted MSI paths, MSI and EXE results, invalid channels, release API failures, version handling, and unsupported operating systems.

Changes

Installer error propagation

Layer / File(s) Summary
Installer failure handling
scripts/install.ps1
Quotes MSI paths and adds reusable MSI and EXE exit-code checks. Validation, release API, artifact, checksum, and unsupported installer failures now throw terminating errors.
Installer failure tests
scripts/tests/OpenHumanWindowsInstall.Tests.ps1
Adds assertion helpers and coverage for quoted MSI arguments, installer results, invalid channels, release API failures, version output, and unsupported operating systems.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Poem

Poem

A rabbit checks each installer run,
MSI and EXE report when done.
Invalid paths now throw with care,
Tests verify each error there,
“Hop!” says the rabbit, “Failures are clear!”

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: Windows installer failures now propagate.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 8, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ce4e78ccf5

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread scripts/install.ps1 Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/install.ps1 (1)

246-249: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Do not report successful MSI reboot codes as failures.

Lines [246-249] emit the failure warning for every nonzero MSI exit code. Exit codes 1641 and 3010 are accepted as successful outcomes by Assert-OpenHumanInstallerProcessSucceeded, so these outcomes still display failure guidance.

Emit the warning only for exit codes outside the accepted MSI success set.

Proposed fix
-    if ($proc.ExitCode -ne 0) {
+    if ($proc.ExitCode -notin @(0, 1641, 3010)) {
       Write-WarnMsg "If this persists, capture a log: msiexec /i `"$tmpFile`" /l*v `"$env:TEMP\OpenHuman-msi.log`""
     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/install.ps1` around lines 246 - 249, Update the warning condition
around Assert-OpenHumanInstallerProcessSucceeded so it excludes MSI exit codes
1641 and 3010, emitting failure guidance only for exit codes outside the
accepted success set while preserving the existing assertion call.
🧹 Nitpick comments (1)
scripts/tests/OpenHumanWindowsInstall.Tests.ps1 (1)

130-149: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Add coverage for the remaining terminating installer paths.

The existing tests cover the shared installer-process helper, invalid channel, version output, and unsupported OS. Add isolated tests for unsupported architecture, missing release artifact, SHA256 mismatch, unsupported installer type, and MSI/EXE failure responses, each asserting the expected terminating error.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/tests/OpenHumanWindowsInstall.Tests.ps1` around lines 130 - 149,
Extend the installer test coverage with isolated terminating-error assertions
for unsupported architecture, missing release artifact, SHA256 mismatch,
unsupported installer type, and MSI/EXE failure responses. Follow the existing
Assert-Throws patterns in OpenHumanWindowsInstall.Tests.ps1, invoke the relevant
installer paths with controlled inputs, and assert each expected error message
without altering the current helper, channel, version, or OS tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@scripts/install.ps1`:
- Around line 246-249: Update the warning condition around
Assert-OpenHumanInstallerProcessSucceeded so it excludes MSI exit codes 1641 and
3010, emitting failure guidance only for exit codes outside the accepted success
set while preserving the existing assertion call.

---

Nitpick comments:
In `@scripts/tests/OpenHumanWindowsInstall.Tests.ps1`:
- Around line 130-149: Extend the installer test coverage with isolated
terminating-error assertions for unsupported architecture, missing release
artifact, SHA256 mismatch, unsupported installer type, and MSI/EXE failure
responses. Follow the existing Assert-Throws patterns in
OpenHumanWindowsInstall.Tests.ps1, invoke the relevant installer paths with
controlled inputs, and assert each expected error message without altering the
current helper, channel, version, or OS tests.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: da5b7ca9-24c8-4635-aa09-36e528d7ef86

📥 Commits

Reviewing files that changed from the base of the PR and between ce4e78c and 78a2e01.

📒 Files selected for processing (2)
  • scripts/install.ps1
  • scripts/tests/OpenHumanWindowsInstall.Tests.ps1

coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 8, 2026
@NgoQuocViet2001

Copy link
Copy Markdown
Contributor Author

Addressed the outside-diff MSI warning finding in 1cccb16: diagnostic guidance is now emitted only for exit codes outside 0, 1641, and 3010. The focused PowerShell suite still passes all 25 checks.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/install.ps1 (1)

178-194: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve release API failures in the terminating error.

When Invoke-RestMethod fails in Lines 178-191, the catch writes a warning and leaves $assetUrl empty. Line 194 then reports “No Windows x64 installer artifact found”, which is incorrect for network, authentication, or rate-limit failures. Rethrow the API error, or include it in the final exception, and reserve the missing-artifact message for a successful release lookup with no matching asset.

Proposed fix
   } catch {
-    Write-WarnMsg "Could not query release API: $($_.Exception.Message)"
+    throw "Could not query release API: $($_.Exception.Message)"
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/install.ps1` around lines 178 - 194, Update the release lookup flow
around Invoke-RestMethod and the catch block so API failures propagate as
terminating errors or are included in the final exception, rather than falling
through with an empty $assetUrl. Keep the “No Windows x64 installer artifact
found” error only for successful release lookups where
Select-OpenHumanWindowsAssetFromRelease returns no matching asset.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@scripts/install.ps1`:
- Around line 178-194: Update the release lookup flow around Invoke-RestMethod
and the catch block so API failures propagate as terminating errors or are
included in the final exception, rather than falling through with an empty
$assetUrl. Keep the “No Windows x64 installer artifact found” error only for
successful release lookups where Select-OpenHumanWindowsAssetFromRelease returns
no matching asset.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a0d39774-2131-48c1-a40d-ae9e09e8ead3

📥 Commits

Reviewing files that changed from the base of the PR and between 78a2e01 and 1cccb16.

📒 Files selected for processing (1)
  • scripts/install.ps1

coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 8, 2026
@NgoQuocViet2001

Copy link
Copy Markdown
Contributor Author

Addressed the release-lookup finding in 7ce63ac: API failures now terminate with their original cause instead of falling through to the missing-artifact message. Added a regression assertion; the focused suite passes all 26 checks.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
scripts/tests/OpenHumanWindowsInstall.Tests.ps1 (1)

130-140: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Add coverage for the new installer failure paths.

Lines 131 through 136 test Assert-OpenHumanInstallerProcessSucceeded directly. They do not execute the MSI and EXE branches in Install-OpenHuman. The suite also does not exercise the unsupported-architecture, missing-artifact, or SHA256-mismatch throws. A wiring regression could therefore pass all 26 checks. Add focused tests with scoped command doubles for process, download, release, and hash operations.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/tests/OpenHumanWindowsInstall.Tests.ps1` around lines 130 - 140,
Extend the installer test suite around Install-OpenHuman to cover its MSI and
EXE execution branches using scoped doubles for process, download, release, and
hash operations. Add focused assertions that unsupported architectures, missing
artifacts, and SHA256 mismatches throw the expected errors, while preserving the
existing direct Assert-OpenHumanInstallerProcessSucceeded checks and
version/argument tests.
scripts/install.ps1 (1)

246-249: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reuse the helper’s MSI success-code policy.

The accepted MSI codes are defined again here as @(0, 1641, 3010), while Assert-OpenHumanInstallerProcessSucceeded defines them at Line 65. Use one shared predicate or constant for both the diagnostic warning and the terminating check. Otherwise, future changes can make the warning behavior diverge from the failure behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/install.ps1` around lines 246 - 249, Update the MSI handling around
Assert-OpenHumanInstallerProcessSucceeded to reuse the helper’s existing
accepted-exit-code policy for the warning condition instead of duplicating @(0,
1641, 3010). Use a shared predicate or constant so the diagnostic warning and
terminating check always remain consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@scripts/install.ps1`:
- Around line 246-249: Update the MSI handling around
Assert-OpenHumanInstallerProcessSucceeded to reuse the helper’s existing
accepted-exit-code policy for the warning condition instead of duplicating @(0,
1641, 3010). Use a shared predicate or constant so the diagnostic warning and
terminating check always remain consistent.

In `@scripts/tests/OpenHumanWindowsInstall.Tests.ps1`:
- Around line 130-140: Extend the installer test suite around Install-OpenHuman
to cover its MSI and EXE execution branches using scoped doubles for process,
download, release, and hash operations. Add focused assertions that unsupported
architectures, missing artifacts, and SHA256 mismatches throw the expected
errors, while preserving the existing direct
Assert-OpenHumanInstallerProcessSucceeded checks and version/argument tests.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: bdab39cd-66fc-41ae-a409-b7c6e6844061

📥 Commits

Reviewing files that changed from the base of the PR and between 1cccb16 and 7ce63ac.

📒 Files selected for processing (2)
  • scripts/install.ps1
  • scripts/tests/OpenHumanWindowsInstall.Tests.ps1

coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 8, 2026
@NgoQuocViet2001

Copy link
Copy Markdown
Contributor Author

Addressed the duplicated MSI success-policy nitpick in f9429ec: warning and assertion paths now call the same predicate. The focused suite remains green at 26 checks.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
scripts/install.ps1 (2)

32-35: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Quote $MsiPath before passing it to Start-Process.

Start-Process -ArgumentList joins the array on spaces, and msiexec requires paths with spaces to be wrapped in double quotes. With a temporary MSI in C:\Temp\Test User\..., this can split the installer path and fail the install.

Proposed fix
-  return @('/i', $MsiPath, '/qn', '/norestart')
+  return @('/i', ('"{0}"' -f $MsiPath), '/qn', '/norestart')
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/install.ps1` around lines 32 - 35, Update the ArgumentList
construction for $MsiPath before it is passed to Start-Process so the MSI path
is wrapped in double quotes, preserving paths containing spaces when msiexec
receives the joined arguments. Keep the existing argument order and other tokens
unchanged.

202-204: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Preserve the API failure error record.

Line 203 wraps Invoke-RestMethod failures in a new exception and drops the original terminating error record. Use bare throw from this catch block to keep the original API failure cause.

Proposed fix
 catch {
-  throw "Could not query release API: $($_.Exception.Message)"
+  throw
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/install.ps1` around lines 202 - 204, Update the catch block around
the release API request to use a bare throw instead of creating a new string
exception, preserving the original Invoke-RestMethod error record and failure
cause.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@scripts/install.ps1`:
- Around line 32-35: Update the ArgumentList construction for $MsiPath before it
is passed to Start-Process so the MSI path is wrapped in double quotes,
preserving paths containing spaces when msiexec receives the joined arguments.
Keep the existing argument order and other tokens unchanged.
- Around line 202-204: Update the catch block around the release API request to
use a bare throw instead of creating a new string exception, preserving the
original Invoke-RestMethod error record and failure cause.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d5ba0002-039a-4881-9120-e83f196264cd

📥 Commits

Reviewing files that changed from the base of the PR and between 7ce63ac and f9429ec.

📒 Files selected for processing (1)
  • scripts/install.ps1

coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 8, 2026
@NgoQuocViet2001

Copy link
Copy Markdown
Contributor Author

Addressed both outside-diff findings in 5d2affb: MSI paths are explicitly quoted before Start-Process joins the argument list, and the release API catch now uses a bare rethrow to preserve the original error record. The focused suite passes all 26 checks.

@NgoQuocViet2001

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant