fix(windows): two bun-on-Windows blockers for browse build + runtime#1601
Open
w-khai wants to merge 2 commits into
Open
fix(windows): two bun-on-Windows blockers for browse build + runtime#1601w-khai wants to merge 2 commits into
w-khai wants to merge 2 commits into
Conversation
Bun's Windows shell parser rejects `(cmd) > file` with:
error: Failed to run script build due to error
Subshells with redirections are currently not supported.
Please open a GitHub issue.
This makes `./setup` fail on every Windows install — the binaries
don't rebuild and the user is left with whatever stale browse.exe
was last committed (or no binary at all on a fresh clone).
Fix: wrap each `(git rev-parse HEAD ...) > path` and the trailing
`(rm -f ...)` cleanup in `bash -c '...'`. The version-stamp behavior
is identical (empty file when not in a git checkout vs SHA when we
are); the build now runs end-to-end on Windows via git-bash + bun
1.3.13.
Verified on Windows 11 + bun 1.3.13 + git-bash:
- Pre-patch: `./setup` aborts during `bun run build`.
- Post-patch: full build completes (~7s on a warm cache), all 5
compiled exes land in their dist dirs, server-node.mjs bundles.
POSIX behaviour is unchanged — bash on macOS / Linux handles either
syntax. No risk to existing platforms.
Bun's compiled-binary `fs.mkdirSync(path, {recursive:true})` throws
EEXIST when the directory already exists. Node does NOT — `recursive:
true` is documented as suppressing EEXIST. The divergence makes every
`browse` invocation on Windows exit 1 with:
[browse] EEXIST: file already exists, mkdir 'C:\...\.gstack'
because ensureStateDir() runs unconditionally at startup and the
project's `.gstack/` exists by then (gitignore'd state dir).
Reproduced on:
- Windows 11 Home (10.0.26200)
- bun 1.3.13
- OneDrive home directory (path contains a space)
- git-bash + plain cmd.exe — both surface the same EEXIST
A plain `node -e "require('fs').mkdirSync('.gstack', {recursive:true})"`
on the same machine + same path succeeds. So the bug is in bun's fs
shim, not in our code or the filesystem. But mkdirSecure can defend
defensively without waiting for an upstream bun fix.
Fix: catch EEXIST in mkdirSecure(), verify the existing path is in
fact a directory (statSync), then fall through to re-apply the ACL.
Throws on any other error code. The behavior on Node is unchanged
(EEXIST is never raised, so the catch never fires).
Verified end-to-end: rebuilt the browse binary with the patch,
re-ran `browse status` and `browse goto https://example.com` — both
return cleanly. Prior to the patch, both exited 1 with the EEXIST.
Without this fix, gstack browse is 100% unusable on Windows.
Contributor
|
Thanks for splitting this into two commits. One collision to call out: the |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Two independent fixes that together unblock gstack browse on Windows. Each commit is self-contained and can be cherry-picked individually.
e0daa44package.json(1 line)./setupfails before binaries rebuild because bun's Windows shell doesn't support(cmd) > filesubshell-with-redirect.376c5cdbrowse/src/file-permissions.ts(+16/-1)browseinvocation on Windows exits 1 withEEXISTbecause bun'sfs.mkdirSync(p, {recursive:true})throws when the dir exists (Node doesn't).Without these two fixes, gstack browse is 100% unusable on Windows. With them, both
./setupandbrowse <cmd>work end-to-end on Windows 11 + bun 1.3.13 + git-bash + OneDrive home directory.Reproduction (pre-patch)
Verification (post-patch)
I drove a full real-app QA walkthrough end-to-end against an in-house SvelteKit + Go project on Windows after the fix landed — 12 browser-side commands across login, form fill, screenshot, JS eval, navigation — zero EEXIST recurrences.
Risk
Both fixes are POSIX no-ops:
package.jsonchange wraps subshell-with-redirect lines inbash -c '...'. Bash on macOS / Linux handles the wrapped form identically to the unwrapped one (it's just one extra fork). I ranbun run buildafter the patch on Windows; can't trivially exercise on macOS from this box but the syntax change is mechanical.mkdirSecureonly ADDS a catch arm forEEXIST(and re-throws everything else). Node'smkdirSync({recursive:true})is documented to never throw EEXIST, so on Linux/macOS this catch arm never fires. ThestatSync+restrictDirectoryPermissionsfollow-through is idempotent.Test plan
For maintainers wanting to reproduce:
./setup.cd <some-project>(any dir is fine; the bug fires on the.gstack/mkdir at browse startup).master(pre-patch):./setupfails on the build script. After commenting out the redirects locally, the resulting binary then fails with EEXIST on everybrowseinvocation../setupandbrowse statuscomplete cleanly.Notes
212912583+w-khai@users.noreply.github.com) because my real email is private.🤖 Generated with Claude Code