Skip to content

bun run build crashes on Windows: "Subshells with redirections are currently not supported" #1530

@scarson

Description

@scarson

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:

  1. 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.
  2. package.json — replace the three subshell-with-redirect patterns with bash scripts/write-versions.sh.
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions