garrytan / garrytan/gstack

browse: Bun.spawn pipe hangs on WSL even with successful compile + HTTP proxy intercepts localhost

Open
#494 1 comment 1 reaction 0 assignees View on GitHub
Dominant language
TypeScript
Stars
133k
Forks
19.9k
Avg merge
18h 46m
Merged PRs (30d)
26

Description

## Summary

On WSL (Ubuntu on Windows), `browse goto ` hangs indefinitely at `[browse] Starting server...` even though the compiled binary and server are functional individually. Two independent root causes discovered.

## Environment

- WSL2 (Ubuntu 24.04) on Windows 11
- gstack v0.11.18.2 (freshly upgraded from 0.3.7)
- Bun 1.3.11
- Chromium (ms-playwright) available and working

## Root Cause 1: Bun.spawn stdio pipe hang

The compiled `browse` binary successfully spawns `bun run server.ts` (verified via `pstree` — full process tree with bun + chrome-headless visible). However, the parent process (CLI) never receives the "server ready" signal via the stdio pipe.

**Evidence:**
- `bun run server.ts` directly: works, state file written in <2s
- `node server-node.mjs` directly: works
- Compiled binary's `Bun.spawn(['bun', 'run', SERVER_SCRIPT], { stdio: ['ignore', 'pipe', 'pipe'] })`: process tree spawns but CLI hangs waiting on pipe

This appears to be a Bun runtime issue where `Bun.spawn` inside a `bun build --compile` binary doesn't properly connect stdio pipes on WSL's filesystem layer.

## Root Cause 2: HTTP proxy intercepts localhost health check

WSL environments commonly have `HTTP_PROXY` set (e.g., for clash/v2ray). The CLI's health check:
```
curl -sf "http://127.0.0.1:$port/health"
```
gets routed through the proxy, which returns 502 for localhost. This causes the "wait for healthy" loop to never succeed even if the server is actually running.

## Workaround

Replace the compiled binary with a bash wrapper that:
1. Starts the server via `nohup bun run server.ts` (avoids Bun.spawn pipe issue)
2. Polls the state file + health endpoint with `--noproxy '*'`
3. Sends commands via HTTP API with `--noproxy '*'`

```bash
#!/usr/bin/env bash
# Key fixes:
# 1. Use nohup + bun run instead of Bun.spawn
# 2. All curl calls use --noproxy '*'
```

Full wrapper: ~80 lines, available on request or as PR.

## Suggested Fix

1. **For Bun.spawn hang:** The `build_or_wrap` approach in PR #412 partially addresses this. Additionally, the CLI's `startServer()` could detect WSL (`uname -r | grep -i microsoft`) and use `child_process.spawn` with `node server-node.mjs` instead of `Bun.spawn(['bun', 'run', ...])`.

2. **For proxy interception:** Add `--noproxy '*'` or `no_proxy=127.0.0.1,localhost` to all internal HTTP calls (health check, command dispatch). This affects WSL, corporate networks, and any environment with HTTP_PROXY set.

## Related

- #407 — `bun build --compile` fails on virtiofs (same class of issue)
- #412 — PR adding wrapper fallback (partial fix for our scenario)
- #486 — Windows browse server fails (Node.js polyfill race condition)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.