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
- Retry with backoff — GitHub Pages outages are usually transient.
- Check network/proxy access to https://googlechromelabs.github.io/chrome-for-testing/ from the failing environment.
- Cache a known-good metadata file locally and pass resolved buildIds directly (exact version strings skip metadata entirely).
- 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
- Allowlist googlechromelabs.github.io in corporate proxies/firewalls.
- Cache metadata JSON locally with a TTL for offline resilience.
- Pin exact buildIds to skip metadata fetches entirely.
- Retry with exponential backoff on transient 5xx.
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
- Chrome channel ${tag} was not found in Chrome-for-Testing me
- Browser download failed (${response.status} ${response.statu
- V2 remote compaction failed (${response.status} ${response.s
- sso-role
- HTTP request failed. status=${response.status}; url=${url};
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/fb43ccc5beee8b78.
Report an issue: GitHub.