Skip to content

fix(jshttp): Chromium exits on Windows with --single-process ("unexpected page type") - #29

Open
Vinicius-Montanari wants to merge 2 commits into
gosom:mainfrom
Vinicius-Montanari:fix/windows-chromium-single-process
Open

Vinicius-Montanari wants to merge 2 commits into
gosom:mainfrom
Vinicius-Montanari:fix/windows-chromium-single-process

Conversation

@Vinicius-Montanari

Copy link
Copy Markdown

Problem

On Windows every JS job fails with unexpected page type
(gosom/google-maps-scraper#322, gosom/google-maps-scraper#309). Two things combine:

  1. newBrowser launches Chromium with --single-process. With the Chromium build used
    by playwright-go v0.6100.0 (Playwright 1.61.1, Chromium 149), this makes the browser
    exit on the first navigation on Windows:
    page.goto: Target page, context or browser has been closed.
    Reproduced with Playwright alone: the same flags fail on the first goto, and the
    same flags without --single-process work.
  2. When recreatePage and recreateContext fail, acquirePage returns
    nil, s.runtime.recreateBrowser(). If the browser is recreated successfully that is
    (nil, nil), so Fetch fails its type assertion with unexpected page type and the
    real error is lost.

Changes

  • launchArgs(goos, disableImages) builds the flag list and only adds --single-process
    on non-Windows platforms. Linux and macOS keep the current flags.
  • acquirePage returns early only when recreateBrowser fails; after a successful
    recreation it falls through to primaryPage().
  • Tests: TestLaunchArgs*, TestSessionSlotReturnsPageAfterBrowserRecreation (fails on
    main) and TestSessionSlotReturnsErrorWhenBrowserRecreationFails.

Testing

  • go test ./adapters/fetchers/jshttp/... passes. TestSessionSlotReturnsPageAfterBrowserRecreation
    fails on main with "expected a page after browser recreation, got nil".
  • go vet ./..., GOOS=linux go build ./... and golangci-lint with the repo config
    (GOOS=linux): 0 issues.
  • End to end on Windows 11 with google-maps-scraper main (d0b51bc), 4 queries,
    -depth 1 -email -c 4:
    • built against scrapemate v1.4.0: 0 results, all 4 seed jobs fail with
      unexpected page type;
    • built with a replace pointing to this branch: 75 places in about 2 minutes and no
      unexpected page type. The only failed jobs were email jobs hitting company websites
      that are down or block the request.
  • Not tested on Linux or macOS. Their launch flags are unchanged, but the acquirePage
    change applies there too and is only covered by the unit tests above. Also not run with
    -race (no cgo toolchain on the test machine). On Windows the root package tests do not build because
    scrapemate_test.go uses syscall.Kill; that is pre-existing and unrelated.

Noticed, not changed here

playwrightPage.isClosed() returns !p.p.IsClosed(), so it is inverted. Because of it
acquirePage never reuses%2

When the primary page could not be reused and both recreatePage and
recreateContext failed, acquirePage returned the result of
recreateBrowser as its error. A successful browser recreation therefore
produced (nil, nil), and Fetch reported the misleading
"unexpected page type" instead of retrying on the fresh browser.

Fall through to primaryPage after a successful browser recreation and
only return early when recreateBrowser itself fails.
With the Chromium build used by playwright-go v0.6100.0 (Playwright
1.61.1, Chromium 149), passing --single-process on Windows makes the
browser exit on the first navigation with "Target page, context or
browser has been closed". Every JS job fails, and through acquirePage
this surfaced as "unexpected page type"
(gosom/google-maps-scraper#322, #309).

Move the launch flags into launchArgs and only add --single-process on
non-Windows platforms, keeping the current behavior there.
@Vinicius-Montanari

Copy link
Copy Markdown
Author

I hit this on Windows 11 with v1.18.1 and traced it to scrapemate. It launches Chromium
with --single-process, and with the current Chromium (149, via Playwright 1.61.1) that
makes the browser exit on the first navigation on Windows. A second bug in acquirePage
then turns that crash into the misleading unexpected page type.

Fix: #29. With it, the same queries that returned nothing on v1.18.1
return results on Windows. After it is merged, google-maps-scraper needs a scrapemate bump.

@gutosk

gutosk commented Oct 19, 2026

Copy link
Copy Markdown

Same failure on macOS, same cause. Keeping --single-process on Linux only (goos == "linux"), instead of dropping it only on Windows, fixes both. Posting the data here for reference.

Environment: macOS 26.6 arm64, playwright-go v0.6100.0 (driver 1.61.1), chrome-headless-shell 1228 (Chromium 149.0.7827.55), google-maps-scraper v1.18.1 with scrapemate v1.4.0.

Playwright only, using the driver playwright-go downloads with the flags, UA and viewport from newBrowser: open a Maps search, wait for div[role='feed'], scroll the feed 5 times.

  • With all flags, the page closes after about 2.5 s (page.evaluate: Target page, context or browser has been closed), 3 of 3 runs.
  • With the same flags minus --single-process: 5 scrolls and 60 places, 3 of 3 runs.
  • Dropping --no-zygote or the image flag instead changes nothing. chrome-headless-shell 1208 (Chromium 145) fails the same way, so this doesn't look like a Chromium 149 regression.

google-maps-scraper v1.18.1, one query, -c 4:

  • with scrapemate v1.4.0: -depth 1 returns 20 places; -depth 3 closes with target closed and leaves an empty results file (exit code 0);
  • with --single-process on Linux only: -depth 3 returns 40 places and -depth 5 returns 60, with no target closed.

That's gosom/google-maps-scraper#338 on macOS. gosom/google-maps-scraper#137 looks like the Windows side.

Why keep it on Linux: the flag came in with 8466b4b ("browser arguments opt", v0.8.2). The same day, google-maps-scraper added its AWS Lambda runtime on top of v0.8.2 (gosom/google-maps-scraper#96). I couldn't test Lambda, so Linux stays as it is.

On top of this branch, the change is the condition, plus moving darwin to the "omit" test:

if goos == "linux" {
	args = append(args, `--single-process`)
}
Workaround on macOS for google-maps-scraper users who build from source
git clone https://github.com/gosom/google-maps-scraper && cd google-maps-scraper
git checkout v1.18.1
go mod vendor
sed -i '' '/--single-process/d' vendor/github.com/gosom/scrapemate/adapters/fetchers/jshttp/jshttp.go
go build -mod=vendor -o google_maps_scraper .

@vinifborgess

Copy link
Copy Markdown

Opened #30 for the inverted isClosed() noted above. Kept separate so this one stays focused.

This branch has not been deployed

No deployments
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