browse connect (headed) fails: setup installs wrong Chromium revision vs compiled binary's pinned Playwright
- Dominant language
- TypeScript
- Stars
- 133k
- Forks
- 19.9k
- Avg merge
- 18h 46m
- Merged PRs (30d)
- 26
Description
## Summary
On a clean install/upgrade, `browse connect` (headed) fails with `Executable doesn't exist at .../ms-playwright/chromium-1208/...` even though `./setup` reported success and headless `browse` works fine. Root cause: the version of Playwright that `./setup` uses to **install** browsers is resolved at runtime (latest) and downloads a different Chromium revision than the one **embedded in the compiled `browse` binary**, and the post-install verification only launches **headless**, so the mismatch is never caught.
## Environment
- gstack `1.55.0.0` (also reproduced on `1.28.0.0` before upgrading)
- macOS arm64, Node v26.0.0, Bun 1.3.11
- Install type: global-git (`~/.claude/skills/gstack`)
## What happens
```
$ browse connect
Launching headed Chromium with extension + terminal agent...
[browse] Connect failed: Server failed to start:
persistentContext: Executable doesn't exist at
~/Library/Caches/ms-playwright/chromium-1208/chrome-mac-arm64/Google Chrome for Testing.app/Contents/MacOS/Google Chrome for Testing
at async launchHeaded (browse/src/browser-manager.ts:557:35)
at async start (browse/src/server.ts:2938:28)
```
Headless `browse` (e.g. `/qa` headless, `goto`, `snapshot`) works perfectly the whole time.
Playwright cache after a fresh `./setup`:
```
chromium_headless_shell-1208 <- present (why headless works)
chromium_headless_shell-1223
chromium-1223 <- full build, WRONG revision
ffmpeg-1011
# chromium-1208 (full) is MISSING -> headed fails
```
## Root cause
1. The compiled `browse` binary (bun `--compile`) embeds a **pinned** Playwright that resolves Chromium **revision 1208** (Chrome for Testing 145.0.7632.6, Playwright 1.58.2).
2. `setup` installs browsers with `bunx playwright install chromium` (setup ~line 483), which resolves **latest** Playwright at runtime (currently 1.60.0 -> revision **1223**). So it downloads the wrong full build.
3. `ensure_playwright_browser()` (setup ~line 252) verifies with a **headless** launch:
```bash
bun --eval 'import { chromium } from "playwright"; const browser = await chromium.launch(); await browser.close();'
```
This passes because `chromium_headless_shell-*` is present, so the missing **full** build (needed by `launchHeaded`) is never detected.
Net: setup's installer Playwright and the compiled binary's Playwright are not the same version, and the verify step only exercises headless. Headed users are broken on a "successful" install.
## Workaround (confirmed fix)
Install the full Chromium at the revision the compiled binary pins:
```bash
bunx playwright@1.58.2 install chromium # downloads chromium-1208 full (~162MB)
browse connect # -> Mode: headed ✅
```
## Suggested fix
- Install browsers using the **same Playwright version embedded in the compiled `browse` binary**, not a runtime-resolved latest. e.g. pin `playwright@` in the setup install step, or expose `browse install-browsers` that shells out to the binary's own embedded Playwright so install and runtime can never drift.
- Make `ensure_playwright_browser()` launch **headed** (or assert the full Chrome-for-Testing executable path exists), so a missing full build fails setup instead of being masked by the cached headless shell.
Contributor guide
Assessment
This issue has not been assessed yet.