{"record":{"id":"83e441c8fca2b6a8","repo":"heygen-com/hyperframes","slug":"failed-to-load-puppeteer-browsers-cause-fix","errorCode":null,"errorMessage":"Failed to load @puppeteer/browsers: ${cause}\nFix: run `npm install` or `bun install` to restore missing packages, then retry.","messagePattern":"Failed to load @puppeteer/browsers: (.+?)\nFix: run `npm install` or `bun install` to restore missing packages, then retry\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"packages/cli/src/browser/manager.ts","lineNumber":16,"sourceCode":"// fallow-ignore-file code-duplication\nimport { execSync, spawnSync } from \"node:child_process\";\nimport { existsSync, mkdirSync, readdirSync, rmSync, statSync, utimesSync } from \"node:fs\";\nimport { basename } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { normalizeErrorMessage } from \"../utils/errorMessage.js\";\n\ntype PuppeteerBrowsers = typeof import(\"@puppeteer/browsers\");\n\nasync function loadPuppeteerBrowsers(): Promise<PuppeteerBrowsers> {\n  try {\n    return await import(\"@puppeteer/browsers\");\n  } catch (err) {\n    const cause = normalizeErrorMessage(err);\n    throw new Error(\n      `Failed to load @puppeteer/browsers: ${cause}\\n` +\n        `Fix: run \\`npm install\\` or \\`bun install\\` to restore missing packages, then retry.`,\n    );\n  }\n}\n\nconst CHROME_VERSION = \"152.0.7928.2\";\nconst CACHE_ROOT_DIR = join(homedir(), \".cache\", \"hyperframes\");\nconst CACHE_DIR = join(homedir(), \".cache\", \"hyperframes\", \"chrome\");\n// Puppeteer's managed cache — where `@puppeteer/browsers install\n// chrome-headless-shell` (and `puppeteer install`) drop binaries. The engine's\n// `resolveHeadlessShellPath` scans the same directory; the CLI must look here\n// too or it silently picks system Chrome over a perfectly good headless-shell.\nconst PUPPETEER_CACHE_DIR = join(homedir(), \".cache\", \"puppeteer\", \"chrome-headless-shell\");\n\n// `@puppeteer/browsers`' install() has no concurrency guard of its own — two\n// CLI invocations that both miss the cache at the same time both extract into\n// the same target directory simultaneously. A killed/interrupted extraction","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/browser/manager.ts#L1-L34","documentation":"Thrown by loadPuppeteerBrowsers() when the dynamic import('@puppeteer/browsers') fails. The CLI lazily imports this package only when it needs to download/manage chrome-headless-shell; if the package is missing from node_modules (incomplete install, monorepo hoist issue, corrupted node_modules), the import rejects and is rewrapped with a restore hint. The underlying cause message is included.","triggerScenarios":"ensureBrowser()/downloadBrowser() calls loadPuppeteerBrowsers(); the `import('@puppeteer/browsers')` throws — package not installed, hoisted away in a monorepo where the CLI package can't resolve it, or node_modules is partially deleted.","commonSituations":"Fresh clone where `bun install` was interrupted; a production deploy that pruned devDependencies and @puppeteer/browsers was marked dev; pnpm-style hoisting incompatibility; manual deletion of part of node_modules.","solutions":["Run `bun install` (or `npm install`) at the repo root to restore missing packages, then retry.","If using a monorepo, ensure @puppeteer/browsers is a real dependency of packages/cli (check packages/cli/package.json).","Clear node_modules and reinstall if the install is partial: remove node_modules, reinstall."],"exampleFix":"# before — missing package\n$ hyperframes render ...\nError: Failed to load @puppeteer/browsers ...\n# restore\n$ bun install\n$ hyperframes render ...","handlingStrategy":"validation","validationCode":"async function puppeteerBrowsersResolvable(): Promise<boolean> {\n  try { await import('@puppeteer/browsers'); return true; } catch { return false; }\n}\nif (!await puppeteerBrowsersResolvable()) {\n  throw new Error('@puppeteer/browsers missing. Run `bun install`.');\n}","typeGuard":null,"tryCatchPattern":"try {\n  await ensureBrowser();\n} catch (err) {\n  if (/Failed to load @puppeteer\\/browsers/i.test((err as Error).message)) {\n    console.error('Run `bun install` to restore packages, then retry.');\n  }\n  throw err;\n}","preventionTips":["Run `bun install` after every pull and before first browser-using command.","In production/CI, don't prune @puppeteer/browsers as a devDependency — verify it is in dependencies.","Pin the version via the lockfile."],"tags":["browser","dependency","install","puppeteer","environment"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}