Summary
On Windows + Git Bash + bun 1.3.13, fresh installs and gstack-upgrade to v1.39.1.0 fail during ./setup's build step with:
error: Subshells with redirections are currently not supported. Please open a GitHub issue.
The error originates from Bun's bundled shell, not from gstack code directly. But the build script in package.json is composed in a way that triggers it.
Reproducer
Environment: Windows 11 Enterprise, Git Bash (MSYS2), bun 1.3.13, gstack f589770 (v1.39.1.0).
git clone https://github.com/garrytan/gstack.git ~/gstack && cd ~/gstack && ./setup
→ Fails at bun run build with the error above.
Minimal reproducer (no gstack required):
bun -e 'await Bun.\`( echo hello ) > /tmp/x.txt\`'
# error: Subshells with redirections are currently not supported.
Root cause
package.json:12 scripts.build contains three subshell-with-stdout-redirection patterns:
```
( git rev-parse HEAD 2>/dev/null || true ) > browse/dist/.version
( git rev-parse HEAD 2>/dev/null || true ) > design/dist/.version
( git rev-parse HEAD 2>/dev/null || true ) > make-pdf/dist/.version
```
Bun's shell on Windows rejects each one. This is a separate hostile pattern from the { cmd; } brace groups that were caught by the regex test in v1.38.0.0 → v1.39.1.0 — the CHANGELOG for v1.39.1.0 notes that the brace-group form regressed during the v1.38.0.0 merge and was replaced with subshells. But subshells-with-redirect are also Bun-Windows-hostile.
Additional Bun shell limitations observed while looking for a safe inline form:
| Pattern |
Bun shell on Windows |
{ cmd; } > file |
rejected (brace group with redirect) |
( cmd ) > file |
rejected (this issue) |
cmd 2>/dev/null > file |
error: expected a command or assignment but got: "Redirect" |
> file cmd |
same as above |
cmd > file (single redirect) |
works |
cmd > file || true |
works |
No single-line inline form of "swallow stderr, swallow exit code, write stdout to a file" parses under Bun shell on Windows. The fix is to delegate to a bash script (or a bun run of a TS helper).
Why CI didn't catch it
test/build-script-shell-compat.test.ts only validates the build script via regex:
test('every `> path/.version` redirect is preceded by a subshell, not a brace group', () => {
...
for (const m of versionRedirects) {
expect(m[1].startsWith('(')).toBe(true);
}
});
It gates on the subshell prefix being present — but subshell-with-redirect is itself the broken pattern, just not the same broken pattern as braces. The regex check green-lights the broken pattern.
windows-free-tests.yml runs four targeted tests, none of which invoke ./setup or bun run build end-to-end. So the regression that surfaces immediately on any Windows install is invisible to CI.
Proposed fix
PR coming separately. Three changes:
scripts/write-versions.sh (new) — bash script that writes HEAD SHA to all three .version files. Matches the precedent of browse/scripts/build-node-server.sh.
package.json — replace the three subshell-with-redirect patterns with bash scripts/write-versions.sh.
test/build-script-shell-compat.test.ts — add three regex-based assertions covering all three hostile patterns ({ cmd; } > file, ( cmd ) > file, cmd 2>/dev/null > file) instead of just brace groups. The existing "must be a subshell" assertion is replaced with one that verifies .version writing is delegated to the bash script.
Verified end-to-end on Windows 11 + Git Bash + bun 1.3.13: bun run build completes, all three .version files contain the correct HEAD SHA.
Test hardening recommendation (follow-up)
Even with strengthened regex coverage, a real defense against this class of regression is to execute bun run build (or a parse-only probe of it) under windows-free-tests.yml. Regex tests can't predict every future Bun shell limitation.
Environment
- OS: Windows 11 Enterprise 10.0.22631
- Shell: Git Bash (MSYS2)
- Bun: 1.3.13 (bf2e2cec)
- gstack: f589770 (v1.39.1.0)
- Hit during upgrade from v1.32.0.0 → v1.39.1.0
Summary
On Windows + Git Bash + bun 1.3.13, fresh installs and
gstack-upgradeto v1.39.1.0 fail during./setup's build step with:The error originates from Bun's bundled shell, not from gstack code directly. But the build script in
package.jsonis composed in a way that triggers it.Reproducer
Environment: Windows 11 Enterprise, Git Bash (MSYS2), bun 1.3.13, gstack
f589770(v1.39.1.0).→ Fails at
bun run buildwith the error above.Minimal reproducer (no gstack required):
Root cause
package.json:12scripts.buildcontains three subshell-with-stdout-redirection patterns:```
( git rev-parse HEAD 2>/dev/null || true ) > browse/dist/.version
( git rev-parse HEAD 2>/dev/null || true ) > design/dist/.version
( git rev-parse HEAD 2>/dev/null || true ) > make-pdf/dist/.version
```
Bun's shell on Windows rejects each one. This is a separate hostile pattern from the
{ cmd; }brace groups that were caught by the regex test in v1.38.0.0 → v1.39.1.0 — the CHANGELOG for v1.39.1.0 notes that the brace-group form regressed during the v1.38.0.0 merge and was replaced with subshells. But subshells-with-redirect are also Bun-Windows-hostile.Additional Bun shell limitations observed while looking for a safe inline form:
{ cmd; } > file( cmd ) > filecmd 2>/dev/null > fileerror: expected a command or assignment but got: "Redirect"> file cmdcmd > file(single redirect)cmd > file || trueNo single-line inline form of "swallow stderr, swallow exit code, write stdout to a file" parses under Bun shell on Windows. The fix is to delegate to a bash script (or a
bun runof a TS helper).Why CI didn't catch it
test/build-script-shell-compat.test.tsonly validates the build script via regex:It gates on the subshell prefix being present — but subshell-with-redirect is itself the broken pattern, just not the same broken pattern as braces. The regex check green-lights the broken pattern.
windows-free-tests.ymlruns four targeted tests, none of which invoke./setuporbun run buildend-to-end. So the regression that surfaces immediately on any Windows install is invisible to CI.Proposed fix
PR coming separately. Three changes:
scripts/write-versions.sh(new) — bash script that writes HEAD SHA to all three.versionfiles. Matches the precedent ofbrowse/scripts/build-node-server.sh.package.json— replace the three subshell-with-redirect patterns withbash scripts/write-versions.sh.test/build-script-shell-compat.test.ts— add three regex-based assertions covering all three hostile patterns ({ cmd; } > file,( cmd ) > file,cmd 2>/dev/null > file) instead of just brace groups. The existing "must be a subshell" assertion is replaced with one that verifies.versionwriting is delegated to the bash script.Verified end-to-end on Windows 11 + Git Bash + bun 1.3.13:
bun run buildcompletes, all three.versionfiles contain the correct HEAD SHA.Test hardening recommendation (follow-up)
Even with strengthened regex coverage, a real defense against this class of regression is to execute
bun run build(or a parse-only probe of it) underwindows-free-tests.yml. Regex tests can't predict every future Bun shell limitation.Environment