Skip to content

fix(desktop): Windows updates no longer fail when one app process is left running - #25831

Open
juliusmarminge wants to merge 2 commits into
mainfrom
fix/issue-25450
Open

juliusmarminge wants to merge 2 commits into
mainfrom
fix/issue-25450

Conversation

@juliusmarminge

Copy link
Copy Markdown
Member

Problem

On Windows, in-app updates fail with Failed to uninstall old application files. Please try running the installer again.: 2 when one T3 Code process is still running from the install folder (for example, a main process that outlived the updater-controlled quit). After that the app comes back on the old version. electron-builder's NSIS FIND_PROCESS check runs (Get-CimInstance Win32_Process | ? {...}).Count -gt 0. In Windows PowerShell 5.1, .Count on a single CimInstance is empty, so with exactly one matching process the installer decides nothing is running and never kills it. The old uninstaller then can't move the locked exe and rolls back. Upstream: electron-userland/electron-builder#10454 (open, unfixed in 26.16.1).

Change

This adds a hunk to the existing patches/app-builder-lib@26.16.1.patch for templates/nsis/include/allowOnlyOneInstallerInstance.nsh:

  • FIND_PROCESS wraps the pipeline in @(...), so .Count is 1 for a single process on PowerShell 5.1 (the upstream proposal).
  • FIND_PROCESS and KILL_PROCESS both skip the installer's or uninstaller's own PID ($$_.ProcessId -ne $pid), the same exclusion upstream's taskkill path already uses. Without it, the corrected count would make an uninstaller running in place from the install folder (the TryInPlace fallback in installUtil.nsh) find and kill itself.

pnpm-lock.yaml only picks up the new patch hash.

Scope and approval

Fixes #25450

Triaged via the automated issue flow.

Verification

  • Compiled installer, before and after. This VM can't run Windows, so I built a real NSIS installer with makensis on Linux through each patched app-builder-lib copy. The probe project is synthetic, with compression: store. I then decoded the installer's UTF-16LE string table. (<var> is how NSIS encodes $INSTDIR/$pid, which are runtime variables.)

    Before (96fc7b9551, main) After (2f9ec15860, head)
    FIND_PROCESS if ((Get-CimInstance … | ? {$_.Path -and …}).Count -gt 0) if (@(Get-CimInstance … | ? {$_.ProcessId -ne <var #180> -and $_.Path -and …}).Count -gt 0)
    KILL_PROCESS Get-CimInstance … | ? {$_.Path -and …} | % { Stop-Process … } Get-CimInstance … | ? {$_.ProcessId -ne <var #180> -and $_.Path -and …} | % { Stop-Process … }

    <var #180> is the same variable as upstream's taskkill /FI "PID ne $pid". There is no literal $pid text in the binary.
    Transcripts: before vs first commit, head. Scripts: nsis-probe-build.mjs, README, decode-installer-strings.py.

  • Filter logic. I ran the expanded commands in PowerShell 7.4.6 against synthetic process objects (own PID 4242):

    Case Count Find exit Kill selects
    none 0 1 none
    self only (in-place uninstaller) 0 1 none
    one leftover app process 1 0 5001
    two app processes 2 0 5001, 5002

    Transcript, script, driver.

  • Patched dependency. The installed package contains both template edits, and the existing NsisTarget.js hunk is unchanged.

  • Tests. vp test run scripts/build-desktop-artifact.test.ts: 42/42 pass. vp run check:changed passes.

  • Not checked. cannot-verify windows. Nothing here runs Windows PowerShell 5.1 with real CimInstance objects or does an end-to-end update on Windows. The PowerShell 7 check covers the filter logic only, not the 5.1 .Count quirk itself. The reporter's separate observation, that the main process sometimes doesn't exit after the updater quit, is not addressed here.

Claude Opus 5.5 (Claude Code, via T3 Code) did the work. GPT-6.1 Sol (Codex) and Claude Opus 5.5 reviewed it.

🤖 Generated with Claude Code

juliusmarminge and others added 2 commits October 27, 2026 07:37
…ore updating

On Windows PowerShell 5.1, `.Count` on a single CimInstance is empty, so
electron-builder's FIND_PROCESS reported "not running" when exactly one
T3 Code process was left in the install folder. KILL_PROCESS was skipped
and the old uninstaller failed with "Failed to uninstall old application
files ...: 2".

Extend the existing app-builder-lib@26.16.1 patch to wrap the pipeline in
`@(...)`, the fix proposed in electron-userland/electron-builder#10454.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When an upgrade runs the old uninstaller in place from the install
directory, the PowerShell process check now finds the uninstaller itself
and Stop-Process kills it. Exclude the installer/uninstaller's own PID in
both PowerShell filters, as the taskkill path already does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Oct 27, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 2f9ec15

Macroscope's review found this PR approvable — This localized Windows installer fix corrects single-process detection in PowerShell 5.1 and prevents the installer from terminating itself. The accompanying lockfile edits only update the dependency patch hash.

You can add or adjust custom eligibility rules. Learn more.

@github-actions

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 5.0 KiB 5.0 KiB +6 B (+0.1%) 6.8 KiB ✅
Codex Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅
Codex Live turn WebSocket wire 1.2 KiB 1.3 KiB +6 B (+0.5%) 2.0 KiB ✅
Codex Live turn WebSocket decoded 21.6 KiB 21.6 KiB 0 B (0.0%) 24.4 KiB ✅
Codex Live turn messages 2 2 0 (0.0%) 8 ✅
Claude Total thread wire 5.0 KiB 5.0 KiB 0 B (0.0%) 6.8 KiB ✅
Claude Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅
Claude Live turn WebSocket wire 1.3 KiB 1.3 KiB 0 B (0.0%) 2.0 KiB ✅
Claude Live turn WebSocket decoded 21.9 KiB 21.9 KiB 0 B (0.0%) 24.4 KiB ✅
Claude Live turn messages 2 2 0 (0.0%) 8 ✅

Baseline: bc8d02f · PR result: 2f9ec15 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@coderabbitai

coderabbitai Bot commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between bc8d02f and 2f9ec15.

Files ignored due to path filters: 1
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
Files selected for processing: 1
  • patches/app-builder-lib@26.16.1.patch

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 0 remain after this review.

Walkthrough

The NSIS installer patch adds UninstallerReader extraction for Linux builds. Its PowerShell process check handles a single result, and process detection and termination exclude the installer’s own PID.

Changes: Linux uninstaller extraction

Layer / File(s) Summary
Use UninstallerReader on Linux
patches/app-builder-lib@26.16.1.patch
Linux NSIS builds now use UninstallerReader to extract the uninstaller, as macOS Catalina builds do.

PowerShell process handling

Layer / File(s) Summary
Detect and terminate app processes
patches/app-builder-lib@26.16.1.patch
The PowerShell process check wraps results in an array before checking .Count. Process detection and termination exclude the current process by PID.

Priority: Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Possibly related PRs

  • pingdotgg/t3code#23965: Changes updater-related quit behavior, a different stage of the Windows update flow.

Suggested reviewers: jahands

Merge Risk: Minimal · up to 2f9ec

No actionable merge-blocking risk remains in the reviewed changes.

Pre-merge checks: Passed 2 · Failed 2

Failed Failed checks: 2 warnings

Check name Status Explanation Resolution
Linked Issues check Warning Issue #25450 has two coding objectives. The patch implements the installer-side objective: FIND_PROCESS uses @(...), and both process commands exclude the installer or uninstaller PID. The reporte… Investigate and fix the Windows main-process teardown hang described in #25450. Add automated coverage where feasible.
Out of Scope Changes check Warning The whole-PR summary reports a Linux NSIS change that makes builds use UninstallerReader. Issue #25450 concerns Windows NSIS process detection and termination. The reported UninstallerReader chang… Remove the unrelated UninstallerReader change from this pull request, or provide concrete evidence that it is required for the #25450 fix.
Passed Passed checks: 2 passed
Check name Status Explanation
Title check Passed The title names the Windows update fix and the single leftover app process, which matches the main change: the NSIS FIND_PROCESS and KILL_PROCESS patch in app-builder-lib. It uses a conventional commi…
Description check Passed The description follows the template and fills in Problem, Change, Scope and approval, and Verification. The Problem section gives the error, the trigger, and the root cause in PowerShell 5.1. The Cha…
Full details: Title check

Explanation

The title names the Windows update fix and the single leftover app process, which matches the main change: the NSIS FIND_PROCESS and KILL_PROCESS patch in app-builder-lib. It uses a conventional commit prefix and is one sentence. It is specific enough for a reviewer scanning history to understand the primary change. It is 81 characters, which is a little long but acceptable.

Full details: Description check

Explanation

The description follows the template and fills in Problem, Change, Scope and approval, and Verification. The Problem section gives the error, the trigger, and the root cause in PowerShell 5.1. The Change section lists both patch hunks and the lockfile update. Scope links issue #25450. Verification gives compiled-installer and filter-logic evidence, test results, and a clear list of what was not checked. Two points are weaker. The Scope section cites an automated triage flow, not a maintainer approval comment. The template asks for a link to the approval comment. The description also says the Linux-built installer was checked, not run on Windows. Neither gap makes the description largely incomplete.

Full details: Linked Issues check

Explanation

Issue #25450 has two coding objectives. The patch implements the installer-side objective: FIND_PROCESS uses @(...), and both process commands exclude the installer or uninstaller PID. The reported build and filter checks support this behavior. The PR does not investigate or fix the separate Windows main-process teardown problem that #25450 also requests. The Windows PowerShell 5.1 and end-to-end limitations are evidence limits, not additional failures.

Resolution

Investigate and fix the Windows main-process teardown hang described in #25450. Add automated coverage where feasible.

Full details: Out of Scope Changes check

Explanation

The whole-PR summary reports a Linux NSIS change that makes builds use UninstallerReader. Issue #25450 concerns Windows NSIS process detection and termination. The reported UninstallerReader change has no stated connection to that objective. The PR description says that only the process-check patch hunk and its lockfile hash changed, so the supplied evidence contains a scope conflict.

Resolution

Remove the unrelated UninstallerReader change from this pull request, or provide concrete evidence that it is required for the #25450 fix.

Finishing Touches
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

This branch has not been deployed

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

Labels

bugfix Fix PR opened by an issue lead; enters the PR loop pr:gate-failed A land gate failed size:M 30-99 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Windows update fails with "Failed to uninstall old application files: 2" when the main process outlives the updater quit

1 participant