fix: make camofox-browser usable on bundled Firefox 135.0.1#6017
Conversation
Three changes that, together, get a fresh `make up` to a working browser
(out of the box, the server starts but every /tabs request fails):
1. server.js: await the async VirtualDisplay.get()
The VirtualDisplay class from camoufox-js returns a Promise from get().
The previous code stored the Promise object directly into vdDisplay, then
passed it to firefox.launch() which coerced it to the string
"[object Promise]" and set that as DISPLAY. Firefox exits with
`Error: cannot open display: [object Promise]`. The log line
`"xvfb virtual display started","display":{}` is the diagnostic
giveaway: JSON.stringify on a Promise produces {}.
Add the missing `await` so vdDisplay is the resolved "":N"" string.
2. package.json: pin playwright-core to 1.51.0
`^1.58.0` resolves to 1.61.0, which sends `viewport.isMobile: false`
to Firefox's Browser.setDefaultViewport CDP method. Firefox 135.0.1
(the version bundled in CAMOUFOX_VERSION) does not describe that
field, so newContext() throws:
"Found property <root>.viewport.isMobile - false which is not
described in this scheme".
Pin to the playwright version contemporary with Firefox 135 (1.51.0).
Note: this pin must move when CAMOUFOX_VERSION is bumped.
3. Makefile: add --shm-size=2g to the docker run
The default Compose shm is 64 MiB, which is too small for Firefox to
map shared memory; the browser process crashes silently after launch.
`--shm-size=2g` matches the upstream Docker best-practice for
Playwright + Firefox in containers.
Reproduction (before the fix):
make down && make build && make up
curl -s -X POST http://localhost:9377/tabs \
-H 'content-type: application/json' \
-d '{"userId":"u","sessionKey":"k","url":"https://example.com"}'
# => HTTP 500
docker logs camofox-browser | grep -E 'cannot open|isMobile|object Promise'
After the fix: HTTP 200, real tabId, GET .../snapshot returns the
accessibility tree, DELETE closes the tab.
|
Quick note for reviewers: This PR fixes the broken The diagnostic trail is in this issue I went through while finding the bugs: the symptom chain ( Two questions for the maintainers:
Happy to address feedback or split this into three PRs (one per bug) if that's preferred for the changelog. |
Verified — can confirm all three bugs on fresh
|
|
Confirming this fix from the npm-deployed path ( The |
|
Yep, unusable without these three fixes. Regretfully, there as no commits from main maintainer for 2-3 weeks... |
|
thanks for the careful debugging here. the motivation was solid: a fresh the missing await and Playwright/Firefox compatibility issue have since been resolved on current the PR is now a single-line Makefile change and is ready to merge. |
Summary
A fresh
make upof@askjo/camofox-browser@1.11.2starts the server (HTTP 200 on/health) but everyPOST /tabsreturns 500. Three independent bugs compound; this PR fixes all three.After this PR: HTTP 200, real
tabId,GET /tabs/{tabId}/snapshot?userId=...returns the accessibility tree,DELETE /tabs/{tabId}?userId=...returns{"ok":true}.Changes
server.js:955vdDisplay = localVirtualDisplay.get();→vdDisplay = await localVirtualDisplay.get();VirtualDisplay.get()isasync. Withoutawait, the Promise object is stored, then coerced to the string"[object Promise]"and set asDISPLAY. Firefox exits withError: cannot open display: [object Promise]. The log line"xvfb virtual display started","display":{}is the diagnostic giveaway (JSON.stringifyon a Promise produces{}).package.json:137"playwright-core": "^1.58.0"→"playwright-core": "1.51.0"^1.58.0resolves to 1.61.0, which sendsviewport.isMobile: falseto Firefox'sBrowser.setDefaultViewportCDP method. Firefox 135.0.1 (pinned viaCAMOUFOX_VERSION) does not describe that field, sonewContext()throws: "Found property<root>.viewport.isMobile- false which is not described in this scheme". 1.51.0 is the playwright version contemporary with Firefox 135.x.Makefile:67docker run ... -p 9377:9377 $(IMAGE)→docker run ... --shm-size=2g -p 9377:9377 $(IMAGE)/dev/shmis 64 MiB, too small for Firefox to map shared memory; the browser process crashes silently after launch.--shm-size=2gis the upstream best-practice for Playwright + Firefox in containers.Repro
Container logs to watch for each fix:
Note on the playwright pin
The
playwright-core: 1.51.0pin is exact, not a range, and is matched to the bundled Camoufox/Firefox version. The two need to move together:CAMOUFOX_VERSIONin theDockerfileis bumped, theplaywright-corepin inpackage.jsonneeds to move to the playwright version released in the same window. The reference is the Playwright release notes — each version names its bundled Firefox.CAMOUFOX_VERSIONto match a playwright that works with^1.58.0, or document the version pairing in arenovate.json/dependabot.ymlconfig so the pins move together.Test plan
make down && make build && make up— clean rebuildGET /healthreturns{"ok":true,"engine":"camoufox","browserConnected":true,"browserRunning":true,...}POST /tabswith example.com returns HTTP 200 +tabIdGET /tabs/{tabId}/snapshot?userId=...returns the accessibility tree (heading "Example Domain",link "Learn more" [e1])DELETE /tabs/{tabId}?userId=...returns{"ok":true}Out of scope / not fixed here
plugins/vnc/) is disabled by default incamofox.config.json. Enabling it would replace the 1x1 Xvfb with a 1920x1080 one. I did not test this path.lib/reporter.jscrash/hang telemetry endpoint — unrelated, and the default config does not enable it.