Skip to content

fix(browse): bump Playwright to ^1.60.0 and pin full Chromium for extension loading - #1565

Closed
stevenbarragan wants to merge 3 commits into
garrytan:mainfrom
stevenbarragan:stevenbarragan/pin-chromium-launch-headed
Closed

stevenbarragan wants to merge 3 commits into
garrytan:mainfrom
stevenbarragan:stevenbarragan/pin-chromium-launch-headed

Conversation

@stevenbarragan

@stevenbarragan stevenbarragan commented May 17, 2026 •

Copy link
Copy Markdown

Summary

Two related fixes for the headless browse daemon:

  • Playwright bump ^1.58.2 → ^1.60.0: Chromium 1208 (bundled by 1.58.2, Chrome 145) fails Flutter Web's FlutterLoader environment compatibility check in headless mode, producing blank pages with webgl: false, no flt-glass-pane, and a pageerror: FlutterLoader could not find a build compatible with configuration and environment. Chromium 1223 (bundled by 1.60.0, Chrome 148) renders Flutter 3.41+ apps correctly in headless. Verified empirically against a Flutter 3.41.9 web build: same browser-manager.ts, same launch args, only the Chromium build differs.

  • launchHeaded() explicit executablePath pin: Playwright 1.49 changed chromium.launch({ headless: true }) to use chrome-headless-shell by default. chrome-headless-shell cannot load Chrome extensions — /open-gstack-browser and /pair-agent depend on the gstack sidebar extension. The headed path (launchPersistentContext({ headless: false })) was unaffected, but we relied on that implicitly. This patch pins executablePath: GSTACK_CHROMIUM_PATH || chromium.executablePath() explicitly so future Playwright changes to launchPersistentContext defaults can't silently break extension loading.

Boundaries respected:

  • GSTACK_CHROMIUM_PATH override still takes priority in both paths
  • No changes to CDP allowlist, stealth args, or any non-Playwright code
  • chrome-headless-shell remains the default for headless $B launches (Playwright 1.49+ behavior, unchanged)

Test plan

  • bun test browse/test/browser-manager-unit.test.ts browse/test/browser-manager-custom-chromium.test.ts — 10/10 pass
  • Full free test suite (bun test browse/test/ test/ make-pdf/test/ --ignore ...) — exit code 0
  • $B goto https://example.com round-trips correctly
  • Flutter 3.41.9 web app: blank page with webgl: false on 1.58.2 → full render with webgl: true, glass: 1, semantics: 10 on 1.60.0

🤖 Generated with Claude Code

@stevenbarragan stevenbarragan changed the title fix(browse): pin full Chromium executablePath in launchHeaded() for Playwright 1.49+ safety fix(browse): bump Playwright to ^1.60.0 for Flutter Web rendering + pin launchHeaded() executable May 17, 2026
…ension loading

Two related fixes:

1. Playwright bump ^1.58.2 → ^1.60.0 (Chromium 1208/Chrome 145 → 1223/Chrome 148).
   Chromium 1208 fails Flutter Web's FlutterLoader environment compatibility check
   in headless mode, producing blank pages with webgl:false and no flt-glass-pane.
   Chromium 1223 (1.60.0) renders Flutter 3.41+ apps correctly in headless.
   Verified empirically: same browse source, same args, only Chromium build differs.

2. launchHeaded() now explicitly passes executablePath: executablePath ||
   chromium.executablePath() to launchPersistentContext. Playwright 1.49 changed
   headless:true to use chrome-headless-shell (which cannot load extensions).
   The headed path was unaffected, but we were relying on that implicitly. This
   pin ensures /open-gstack-browser and /pair-agent keep loading the sidebar
   extension if Playwright ever changes launchPersistentContext defaults.

GSTACK_CHROMIUM_PATH still takes priority in both paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@stevenbarragan
stevenbarragan force-pushed the stevenbarragan/pin-chromium-launch-headed branch from d9286e8 to ecf7efb Compare May 17, 2026 17:00
@stevenbarragan stevenbarragan changed the title fix(browse): bump Playwright to ^1.60.0 for Flutter Web rendering + pin launchHeaded() executable fix(browse): bump Playwright to ^1.60.0 and pin full Chromium for extension loading May 17, 2026
@jzeng151

Copy link
Copy Markdown

Heads up — this bump also fixes a more severe issue not mentioned in the PR description: playwright install chromium hangs
indefinitely during extraction on Node 26+ with Playwright ≤ 1.59.x, which fully blocks ./setup for new users on those Node
versions. I hit it twice in a row today (Node v26.1.0, gstack@HEAD): zip downloads fine (167MB), then extraction stalls at
~18MB with all worker threads parked in futex_wait/do_epoll_wait and zero CPU growth.

Root cause is fd-slicer's stream _destroy lifecycle, which never emits close on Node 26 — see
microsoft/playwright#40724. The fix vendors patched yauzl 3.2.1
(microsoft/playwright#40747, merged 2026-05-09) and first ships in
Playwright v1.60.0 — exactly what this PR pulls in. Confirmed locally that bumping to ^1.60.0 lets bunx playwright install chromium complete normally.

…romium-launch-headed

* origin/main:
  v1.42.1.0 feat: gate terminal-agent teardown on ServerConfig.ownsTerminalAgent (unblocks gbrowser embedder) (garrytan#1615)
  v1.42.0.0 Daegu wave: 23 community-filed bugs + PTY classifier enforcement (24 bisect commits) (garrytan#1594)
  v1.41.1.0 fix wave: 7 HIGH bugs from external audit + regression tests (PR garrytan#1169 follow-up) (garrytan#1592)
…romium-launch-headed

* origin/main: (35 commits)
  v1.58.1.0 feat: hermetic local E2E + Conductor prose AskUserQuestion (garrytan#2004)
  v1.58.0.0 feat: diagram + multi-format document engine (mermaid, excalidraw, single-file HTML, DOCX) (garrytan#1990)
  v1.57.10.0 feat: Codex review default-on across review/ship/plan/docs (garrytan#1966)
  v1.57.9.0 feat: source-clean gbrain render (dev-setup --out-dir + machine-wide gbrain-refresh) (garrytan#1951)
  v1.57.8.0 feat: browse js/eval --out render-to-file (canonical Chromium for offline rendering) (garrytan#1929)
  v1.57.7.0 feat: GSTACK REVIEW REPORT always declares unresolved decisions (garrytan#1916)
  v1.57.6.0 fix wave: 8 community bugs (4 security guards failing open) (garrytan#1911)
  v1.57.5.0 feat: cross-session decision memory + gbrain dream-stage call graph (garrytan#1910)
  v1.57.4.0 refactor(ethos): rename Boil the Lake principle to Boil the Ocean (garrytan#1912)
  v1.57.3.0 fix(ship): always-loaded PR-title-version rule + fork-PR title-sync backstop (garrytan#1909)
  v1.57.2.0 feat: AskUserQuestion prose fallback when the tool fails at runtime (garrytan#1908)
  v1.57.0.0 feat: carve-guard system + carve cso/document-release/design-consultation (garrytan#1907)
  v1.56.1.0 fix(sync): staging-dir ownership guard + resume-correctness fixes (garrytan#1802) (garrytan#1856)
  v1.56.0.0 Token-reduction Phase B + AUQ paranoid safety net (garrytan#1849)
  v1.55.1.0 fix: telemetry consent accuracy + gstack-slug cache sanitization (garrytan#1848)
  v1.55.0.0 fix wave: gbrain data-loss guards + browser crash-loop + 6 more (garrytan#1808)
  fix(setup): add missing gen:skill-docs:user script (garrytan#1807)
  v1.54.0.0 feat: carve /ship into skeleton + on-demand sections (-59% always-loaded) (garrytan#1806)
  v1.53.1.0 fix: non-interactive-safe plan-tune hook install (flags + smart defaults) (garrytan#1805)
  v1.53.0.0 feat: smarter redaction — PII/secrets/legal guard across /spec, /ship, /cso, /document-* (garrytan#1797)
  ...
@time-attack

Copy link
Copy Markdown
Contributor

@16francej Merge this version because it fully updates the Playwright 1.60 manifest and lockfile, preserves the custom Chromium path, and fixes the reproduced Node 24 problem.

@capy-ai

capy-ai Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Thanks for this, @stevenbarragan. The fix is now on main: Playwright is now ^1.62.1 (package.json) (already on main as of v1.91.16.0). Closing as superseded; if you still see the problem on the latest gstack, please open an issue with ./setup --status output.

@capy-ai capy-ai Bot closed this Oct 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants