garrytan / garrytan/gstack

browse connect (headed) fails: setup installs wrong Chromium revision vs compiled binary's pinned Playwright

Open
#1,829 2 comments 0 reactions 0 assignees View on GitHub
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

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.