Summary
The playwright-core remote browser path used by @playwright/cli does not pass browserName when connecting to a raw Playwright run-server endpoint. The remote server then receives no x-playwright-browser header and fails while trying to launch an undefined browser type.
This shows up in @playwright/cli when using browser.remoteEndpoint in .playwright/cli.config.json.
Related user-facing CLI issue: microsoft/playwright-cli#408
Use Case
We run a development container with @playwright/cli installed and a separate Playwright service container running:
npx -y playwright@1.60.0 run-server --port 3456 --host 0.0.0.0
Our E2E tests already use this pattern successfully via @playwright/test and chromium.connect(...). We want @playwright/cli to connect to the same remote browser service via:
{
"browser": {
"browserName": "chromium",
"isolated": true,
"remoteEndpoint": "ws://playwright:3456/",
"launchOptions": {
"channel": "chrome"
}
}
}
Actual Behavior
playwright-cli open https://example.com --config=.playwright/cli.config.json fails with:
Cannot read properties of undefined (reading 'launch')
Debug output shows the inner server-side error:
TypeError: Cannot read properties of undefined (reading 'launch')
at PlaywrightServer._initLaunchBrowserMode
Root Cause
In the remote browser path, createRemoteBrowser(config) calls connectToBrowser() without forwarding config.browser.browserName:
const endpoint = config.browser.remoteEndpoint;
const playwrightObject = playwright;
const browser = await connectToBrowser(playwrightObject, { endpoint });
browser._connectToBrowserType(playwrightObject[browser._browserName], {}, void 0);
But connectToBrowser() only sends the browser type to the server when params.browserName is present:
const nameParam = params.browserName ? { "x-playwright-browser": params.browserName } : {};
Because browserName is omitted, the remote run-server endpoint cannot select a browser type to launch.
Proposed Fix
Pass the configured browser name into connectToBrowser():
const endpoint = config.browser.remoteEndpoint;
const playwrightObject = playwright;
-const browser = await connectToBrowser(playwrightObject, { endpoint });
+const browser = await connectToBrowser(playwrightObject, {
+ endpoint,
+ browserName: config.browser.browserName,
+});
browser._connectToBrowserType(playwrightObject[browser._browserName], {}, void 0);
Local Validation
We patched the installed bundled playwright-core locally with the change above. With:
@playwright/cli@0.1.11
- matching remote
playwright@1.60.0-alpha-1777669338000
- matching browser revision installed in the server container
browser.isolated: true
the CLI successfully opened the page:
### Browser opened
### Ran Playwright code
await page.goto('https://example.com');
### Page
- Page URL: https://example.com/
- Page Title: Example Domain
browser.isolated: true is still needed because run-server returns a browser without an existing default context, but the undefined launch failure is fixed by forwarding browserName.
Summary
The
playwright-coreremote browser path used by@playwright/clidoes not passbrowserNamewhen connecting to a raw Playwrightrun-serverendpoint. The remote server then receives nox-playwright-browserheader and fails while trying to launch an undefined browser type.This shows up in
@playwright/cliwhen usingbrowser.remoteEndpointin.playwright/cli.config.json.Related user-facing CLI issue: microsoft/playwright-cli#408
Use Case
We run a development container with
@playwright/cliinstalled and a separate Playwright service container running:Our E2E tests already use this pattern successfully via
@playwright/testandchromium.connect(...). We want@playwright/clito connect to the same remote browser service via:{ "browser": { "browserName": "chromium", "isolated": true, "remoteEndpoint": "ws://playwright:3456/", "launchOptions": { "channel": "chrome" } } }Actual Behavior
playwright-cli open https://example.com --config=.playwright/cli.config.jsonfails with:Debug output shows the inner server-side error:
Root Cause
In the remote browser path,
createRemoteBrowser(config)callsconnectToBrowser()without forwardingconfig.browser.browserName:But
connectToBrowser()only sends the browser type to the server whenparams.browserNameis present:Because
browserNameis omitted, the remoterun-serverendpoint cannot select a browser type to launch.Proposed Fix
Pass the configured browser name into
connectToBrowser():Local Validation
We patched the installed bundled
playwright-corelocally with the change above. With:@playwright/cli@0.1.11playwright@1.60.0-alpha-1777669338000browser.isolated: truethe CLI successfully opened the page:
browser.isolated: trueis still needed becauserun-serverreturns a browser without an existing default context, but theundefined launchfailure is fixed by forwardingbrowserName.