can1357/oh-my-pi · error · Error

Unable to safely override process.cwd for Puppeteer import

Error message

Unable to safely override process.cwd for Puppeteer import

What it means

Before importing puppeteer-core, importPuppeteerWithSafeCwd temporarily replaces process.cwd with a function returning a safe directory (Puppeteer's cosmiconfig probes cwd during module init). If process.cwd has no own property descriptor whose value is a function — e.g. it was already replaced, deleted, or made non-configurable by other instrumentation — the override is deemed unsafe and this Error is thrown, and the failure is cached (puppeteerCwdFailed) so later imports rethrow it.

Source

Thrown at packages/coding-agent/src/tools/browser/launch.ts:88

}

const STEALTH_ACCEPT_LANGUAGE = "en-US,en";

const USER_AGENT_TARGET_TIMEOUT_MS = 5_000;
const USER_AGENT_TARGET_TYPES = new Set(["page", "webview", "background_page"]);
const PUPPETEER_SOURCE_URL_SUFFIX = "//# sourceURL=__puppeteer_evaluation_script__";

/**
 * Lazy-import puppeteer while hiding the user's cwd from cosmiconfig. The
 * import must not change the filesystem cwd: it is awaited and callers
 * continue running on the main thread while it is pending.
 */
let puppeteerCwdFailed = false;
let puppeteerCwdFailure: unknown;
async function importPuppeteerWithSafeCwd(safeDir: string): Promise<typeof Puppeteer> {
	const cwdDescriptor = Object.getOwnPropertyDescriptor(process, "cwd");
	if (!cwdDescriptor || typeof cwdDescriptor.value !== "function") {
		throw new Error("Unable to safely override process.cwd for Puppeteer import");
	}

	try {
		Object.defineProperty(process, "cwd", { ...cwdDescriptor, value: () => safeDir });
	} catch (overrideFailure) {
		puppeteerCwdFailed = true;
		puppeteerCwdFailure = overrideFailure;
		throw overrideFailure;
	}
	let loaded: typeof Puppeteer | undefined;
	let importFailure: unknown;
	let importFailed = false;
	let restorationFailure: unknown;
	let restorationFailed = false;
	try {
		try {
			// Dynamic import is intentional: Puppeteer probes cwd during module initialization.
			loaded = (await import("puppeteer-core")).default;

View on GitHub (pinned to 9690622007)

Solutions

  1. Find and remove whatever redefines/deletes process.cwd before browser tooling runs (search for defineProperty(process, "cwd") / process.cwd = in the host code)
  2. Ensure the original descriptor is restored after any intentional cwd override elsewhere
  3. Restart the process to clear the cached puppeteerCwdFailed failure after fixing the cause
  4. As a workaround, launch against an already-running browser (connected CDP kind) that skips the puppeteer import path if available

Example fix

// before: test stub without restoring
process.cwd = () => "/fake"; // or defineProperty with configurable:false
// after: patch and restore with a matching descriptor
const desc = Object.getOwnPropertyDescriptor(process, "cwd")!;
Object.defineProperty(process, "cwd", { ...desc, value: () => "/fake" });
// ...test...
Object.defineProperty(process, "cwd", desc);
Defensive patterns

Strategy: try-catch

Validate before calling

const d = Object.getOwnPropertyDescriptor(process, "cwd");
if (!d || typeof d.value !== "function") {
  throw new Error("process.cwd is not safely patchable; remove global cwd monkey-patching before using the browser tool");
}

Type guard

function cwdIsPatchable(): boolean {
  const d = Object.getOwnPropertyDescriptor(process, "cwd");
  return !!d && typeof d.value === "function";
}

Try / catch

try {
  await loadPuppeteer();
} catch (err) {
  if (err instanceof Error && err.message.includes("Unable to safely override process.cwd")) {
    // find the library that replaced/deleted process.cwd and remove/repair that patch, then restart
  }
  throw err;
}

Prevention

When it happens

Trigger: Another library/test framework monkey-patched or deleted process.cwd (Object.defineProperty(process,'cwd',{...}) or deletion) before the browser tool first imports puppeteer; bundlers/runtimes exposing a non-configurable cwd; a prior import attempt failed to restore cwd (restorationFailed sets puppeteerCwdFailed).

Common situations: Test harnesses that stub process.cwd globally; running under instrumentation that freezes globals; a previous failed puppeteer load poisoning the cached failure for the process lifetime.

Related errors


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