can1357/oh-my-pi · error · Error

Failed to fetch Chrome-for-Testing metadata (${response.stat

Error message

Failed to fetch Chrome-for-Testing metadata (${response.status} ${response.statusText})

What it means

fetchMetadata fetches Chrome-for-Testing JSON metadata (last-known-good-versions, latest-versions-per-milestone, known-good-versions) from googlechromelabs.github.io; when the HTTP response is not ok it throws with the status and statusText. This is a network/service-level failure upstream of version resolution.

Source

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

function chromeChannelName(tag: string): string | undefined {
	switch (tag) {
		case BrowserTag.STABLE:
			return "Stable";
		case BrowserTag.BETA:
			return "Beta";
		case BrowserTag.DEV:
			return "Dev";
		case BrowserTag.CANARY:
			return "Canary";
		default:
			return undefined;
	}
}

async function fetchMetadata<T>(filename: string): Promise<T> {
	const response = await fetch(`${CHROME_METADATA_BASE_URL}/${filename}`);
	if (!response.ok)
		throw new Error(`Failed to fetch Chrome-for-Testing metadata (${response.status} ${response.statusText})`);
	return (await response.json()) as T;
}

function chromeArchivePlatform(platform: BrowserPlatform): string {
	switch (platform) {
		case BrowserPlatform.LINUX:
		case BrowserPlatform.LINUX_ARM:
			return "linux64";
		case BrowserPlatform.MAC:
			return "mac-x64";
		case BrowserPlatform.MAC_ARM:
			return "mac-arm64";
		case BrowserPlatform.WIN32:
			return "win32";
		case BrowserPlatform.WIN64:
			return "win64";
	}
}

View on GitHub (pinned to 9690622007)

Solutions

  1. Retry with backoff — GitHub Pages outages are usually transient.
  2. Check network/proxy access to https://googlechromelabs.github.io/chrome-for-testing/ from the failing environment.
  3. Cache a known-good metadata file locally and pass resolved buildIds directly (exact version strings skip metadata entirely).
  4. Pin buildIds in config to avoid metadata fetches at runtime.

Example fix

// before
const buildId = await resolveBuildId(Browser.CHROME, platform, BrowserTag.STABLE); // fetch fails
// after
const buildId = process.env.CHROME_BUILD_ID ?? await resolveBuildId(Browser.CHROME, platform, BrowserTag.STABLE);
Defensive patterns

Strategy: retry

Validate before calling

// probe metadata availability before resolving versions
const res = await fetch('https://googlechromelabs.github.io/chrome-for-testing/last-known-good-versions.json');
if (!res.ok) throw new Error(`CfT metadata unreachable (${res.status}); pin a buildId or retry later`);

Type guard

null

Try / catch

async function resolveWithRetry(...args: Parameters<typeof resolveBuildId>) {
  for (let attempt = 0; ; attempt++) {
    try {
      return await resolveBuildId(...args);
    } catch (err) {
      if (/Failed to fetch Chrome-for-Testing metadata/.test(String(err)) && attempt < 3) {
        await Bun.sleep(2 ** attempt * 1000); // backoff for transient GitHub Pages outages
        continue;
      }
      throw err;
    }
  }
}

Prevention

When it happens

Trigger: Any call chain that resolves versions — resolveBuildId for channels or milestones — when the metadata request returns a non-2xx status (404 for a renamed file, 403 rate-limit/block, 5xx outage, captive-portal 200->no wait, non-ok only).

Common situations: Corporate proxies blocking googlechromelabs.github.io; GitHub Pages outage (5xx); DNS/connectivity issues surfacing as fetch errors earlier; stale pinned metadata URLs after an upstream rename.

Related errors


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