Skip to content

Fix Windows build: exclude pi-coding-agent from packaged app#3727

Closed
wojtekn wants to merge 4 commits into
trunkfrom
fix-windows-path-too-long
Closed

Fix Windows build: exclude pi-coding-agent from packaged app#3727
wojtekn wants to merge 4 commits into
trunkfrom
fix-windows-path-too-long

Conversation

@wojtekn

@wojtekn wojtekn commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Related issues

Follows up on #3707 (migrate @mariozechner/pi-* to @earendil-works/pi-*).

How AI was used in this PR

Claude Code diagnosed the root cause and wrote the fix.

Proposed Changes

After #3707 landed, the Windows Squirrel build started failing with:

The specified path, file name, or both are too long. The fully qualified file name
must be less than 260 characters, and the directory name must be less than 248 characters.

Root cause: @earendil-works/pi-coding-agent is a devDependency of apps/studio (only needed for import type { SessionEntry } — erased at compile time). However, after install:bundle runs npm install --no-workspaces, galactus (electron-packager's DestroyerOfModules) doesn't reliably prune the nested node_modules under pi-coding-agent. Its transitive @mistralai/mistralai dependency contains filenames like getchatcompletionfieldoptionscountsv1observability...post.js that reach 200+ chars on their own. With the Windows build agent prefix (C:\buildkite-agent\builds\ci-windows-...\automattic\studio\) the total path hits ~295 chars — 35 over the 260-char limit.

The fix adds an explicit ignore pattern to forge.config.ts so electron-forge never copies pi-coding-agent into the packaged output, regardless of whether the devDep prune works. This is a belt-and-suspenders approach since the package should already be excluded as a devDep.

Testing Instructions

  • Windows build should pass (Squirrel maker no longer encounters long paths)
  • macOS and Linux builds unaffected (no 260-char path limit)
  • App functionality unchanged — pi-coding-agent was only imported for TypeScript types, not included at runtime

Pre-merge Checklist

  • I have checked this code is correct to the best of my ability
  • I have tested this change on a supported platform
  • My changes generate no new deprecation warnings

… path-too-long error

@earendil-works/pi-coding-agent is a devDependency used only for TypeScript
types (import type). Its transitive @mistralai/mistralai dep contains filenames
like getchatcompletionfieldoptionscountsv1...post.js that, when nested under
pi-coding-agent/node_modules/, exceed Windows' 260-char path limit and cause the
Squirrel/NuGet maker to fail.

galactus (DestroyerOfModules) should prune devDeps from the packaged output, but
after install:bundle's standalone npm install the pruning doesn't reliably remove
the nested node_modules. Adding an explicit forge ignore pattern is a reliable
safety net.
@wojtekn wojtekn requested review from a team and youknowriad June 8, 2026 16:19
@wpmobilebot

wpmobilebot commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

📊 Performance Test Results

Comparing b4b995d vs trunk

app-size

Metric trunk b4b995d Diff Change
App Size (Mac) 1384.35 MB 1384.35 MB +0.00 MB ⚪ 0.0%

site-editor

Metric trunk b4b995d Diff Change
load 1604 ms 1643 ms +39 ms ⚪ 0.0%

site-startup

Metric trunk b4b995d Diff Change
siteCreation 9063 ms 9026 ms 37 ms ⚪ 0.0%
siteStartup 4407 ms 4414 ms +7 ms ⚪ 0.0%

Results are median values from multiple test runs.

Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff)

wojtekn added 3 commits June 8, 2026 20:07
electron-winstaller ships nuget.exe v4.0, which predates long-path support.
Long paths require nuget.exe >= 4.8 AND the LongPathsEnabled registry key.
Download the latest nuget.exe at build time to satisfy both conditions.

Also removes the forge ignore workarounds for pi-coding-agent, react-native
and @react-native that were added to work around the old NuGet limitation.
Write-Host "--- :windows: Enabling long path support"
New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" `
-Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force
If ($LastExitCode -ne 0) { Exit $LastExitCode }

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.

Interesting. The AMI already should enable long paths with these instructions:

Write-Output "Enable long path behavior"
# See:
#
# - https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file#maximum-path-length-limitation
# - https://support.atlassian.com/bamboo/kb/git-checkouts-fail-on-windows-with-filename-too-long-error-unable-to-create-file-errors/
Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem' -Name 'LongPathsEnabled' -Value 1
git config --system core.longpaths true

I see this command adds -PropertyType DWORD -Force which maybe should be pushed upstream to the AMI, too.

However, it's hard to tell whether the issue is with the original command or with electron-winstaller below. That is, I wonder if the latest stable version of that package will work without the additional params in the long-path configuration.

@mokagio

mokagio commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Discovered with Claude: The LongPathsEnabled registry key does not seem to reach the binary that's actually throwing.

The failure is in Squirrel's bundled Update.exe, which uses the legacy .NET Framework path handling. The stack trace from build 17201 suggest it:

System.AggregateException: One or more errors occurred.
 ---> System.IO.PathTooLongException: The specified path, file name, or both are too long.
      The fully qualified file name must be less than 260 characters, and the directory
      name must be less than 248 characters.
   at System.IO.Path.LegacyNormalizePath(String path, Boolean fullCheck, Int32 maxPathLength, Boolean expandShortPaths)
   at System.IO.Path.InternalGetDirectoryName(String path)
   at Squirrel.ReleasePackage.<>c__DisplayClass14_0.b__0()
   at System.Threading.Tasks.Task.Execute()
   --- End of inner exception stack trace ---
   at Squirrel.ReleasePackage.CreateReleasePackage(String outputFile, String packagesRootDir, ...)
   at Squirrel.Update.Program.Releasify(...)
   at Squirrel.Update.Program.main(String[] args)

The key frame is System.IO.Path.LegacyNormalizePath.

@mokagio

mokagio commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

I researched an alternative with AI and pushed it in #3735

@wojtekn

wojtekn commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

Closing in favor of #3735

@wojtekn wojtekn closed this Jun 9, 2026
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.

3 participants