can1357/oh-my-pi · error · Error

Unsupported browser executable: ${options.browser}

Error message

Unsupported browser executable: ${options.browser}

What it means

After resolving the platform, computeExecutablePath verifies the requested product is Chrome; any other Browser value throws this Error because the executable layout (chrome-linux64/chrome, chrome-mac-arm64/..., chrome-win64/chrome.exe) is Chrome-specific. It is a capability guard mirroring getDownloadUrl's restriction.

Source

Thrown at packages/utils/src/browsers.ts:168

/** Return the Chrome-for-Testing archive URL for a browser build. */
export function getDownloadUrl(
	browser: Browser,
	platform: BrowserPlatform,
	buildId: string,
	baseUrl = CHROME_FOR_TESTING_BASE_URL,
): URL {
	if (browser !== Browser.CHROME) throw new Error(`Unsupported browser download: ${browser}`);
	const archivePlatform = chromeArchivePlatform(platform);
	const root = baseUrl.replace(/\/$/, "");
	return new URL(`${root}/${buildId}/${archivePlatform}/chrome-${archivePlatform}.zip`);
}

/** Compute the executable path in Puppeteer's cache layout. */
export function computeExecutablePath(options: ComputeExecutablePathOptions): string {
	const platform = options.platform ?? detectBrowserPlatform();
	if (!platform) throw new Error("Cannot determine a browser platform for this host");
	if (options.browser !== Browser.CHROME) throw new Error(`Unsupported browser executable: ${options.browser}`);
	const installDir = installationDir(options.cacheDir, options.browser, platform, options.buildId);
	switch (platform) {
		case BrowserPlatform.LINUX:
		case BrowserPlatform.LINUX_ARM:
			return path.join(installDir, "chrome-linux64", "chrome");
		case BrowserPlatform.MAC:
			return path.join(
				installDir,
				"chrome-mac-x64",
				"Google Chrome for Testing.app",
				"Contents",
				"MacOS",
				"Google Chrome for Testing",
			);
		case BrowserPlatform.MAC_ARM:
			return path.join(
				installDir,
				"chrome-mac-arm64",

View on GitHub (pinned to 9690622007)

Solutions

  1. Only pass Browser.CHROME to computeExecutablePath / executablePath.
  2. Resolve other products' executables with @puppeteer/browsers or product-specific path logic.
  3. Filter your browser collection to CHROME before computing paths.

Example fix

// before
for (const b of [Browser.CHROME, Browser.CHROMEDRIVER]) executablePath({ browser: b, buildId });
// after
for (const b of [Browser.CHROME, Browser.CHROMEDRIVER]) {
  if (b === Browser.CHROME) executablePath({ browser: b, buildId });
}
Defensive patterns

Strategy: type-guard

Validate before calling

import { Browser } from './browsers';
if (options.browser !== Browser.CHROME) {
  throw new Error(`executablePath supports only chrome; got ${options.browser}`);
}

Type guard

function isChrome(browser: Browser): browser is Browser.CHROME {
  return browser === Browser.CHROME;
}

Try / catch

try {
  return executablePath({ browser, buildId, cacheDir });
} catch (err) {
  if (/^Unsupported browser executable: /.test(String(err))) {
    // fall back to @puppeteer/browsers' computeExecutablePath for other products
  } else throw err;
}

Prevention

When it happens

Trigger: Calling computeExecutablePath({ browser: Browser.CHROMIUM | FIREFOX | CHROMEHEADLESSSHELL | CHROMEDRIVER, buildId, cacheDir }) — directly or via executablePath()/getInstalledBrowsers() with a non-Chrome browser value.

Common situations: Listing multiple browsers in config (chrome + chromedriver) and iterating executablePath over all of them; assuming headless-shell shares Chrome's install layout.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/7c49a6f21bc9d8fc. Report an issue: GitHub.