can1357/oh-my-pi · error · RequestInterceptionCleanupError

Failed to clear browser request interception after browser.r

Error message

Failed to clear browser request interception after browser.run

What it means

After a `browser.run` completes, the worker disables puppeteer request interception (`page.setRequestInterception(false)`) with a timeout. If disabling fails or times out, the cleanup error is rethrown as RequestInterceptionCleanupError so interception state never leaks silently into subsequent operations.

Source

Thrown at packages/coding-agent/src/tools/browser/tab-worker.ts:640

		async cleanup() {
			if (onDescriptor) Object.defineProperty(page, "on", onDescriptor);
			else Reflect.deleteProperty(page, "on");
			if (offDescriptor) Object.defineProperty(page, "off", offDescriptor);
			else Reflect.deleteProperty(page, "off");
			if (onceDescriptor) Object.defineProperty(page, "once", onceDescriptor);
			else Reflect.deleteProperty(page, "once");
			if (removeAllDescriptor) Object.defineProperty(page, "removeAllListeners", removeAllDescriptor);
			else Reflect.deleteProperty(page, "removeAllListeners");
			for (const handler of requestHandlers) Reflect.apply(off, page, ["request", handler]);
			requestHandlers.length = 0;
			try {
				await withTimeout(
					page.setRequestInterception(false),
					REQUEST_INTERCEPTION_CLEANUP_TIMEOUT_MS,
					"Timed out clearing browser request interception",
				);
			} catch (error) {
				throw new RequestInterceptionCleanupError(
					"Failed to clear browser request interception after browser.run",
					{
						error: error instanceof Error ? error.message : String(error),
					},
				);
			}
		},
	};
}

function errorPayload(error: unknown): RunErrorPayload {
	const recoverTab = error instanceof RequestInterceptionCleanupError || undefined;
	if (error instanceof ToolAbortError) {
		return { name: error.name, message: error.message, stack: error.stack, isToolError: false, isAbort: true };
	}
	if (error instanceof ToolError) {
		return {
			name: error.name,

View on GitHub (pinned to 9690622007)

Solutions

  1. Inspect the wrapped `error` field: fix the underlying cause (typically an un-settled request handler in the run script).
  2. Ensure your interception handler never blocks indefinitely — always call request.continue()/abort()/fulfill().
  3. Retry browser.run; transient protocol stalls usually clear on a fresh run.
  4. If the browser is wedged, restart the browser/tab so a clean page is used for the next run.

Example fix

// before
await page.setRequestInterception(true);
page.on("request", req => doAsyncWork(req)); // may hang
// after
page.on("request", req => {
  Promise.race([doAsyncWork(req), Bun.sleep(5000)]).finally(() => req.continue().catch(() => {}));
});
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await browser.run(script);
} catch (err) {
  if (err instanceof RequestInterceptionCleanupError) {
    logger.warn("interception cleanup failed", { cause: err.data?.error });
    await restartBrowser(); // clear wedged state
  } else throw err;
}

Prevention

When it happens

Trigger: A page stuck in a long-running request handler/puppeteer request-interception callback while cleanup tries to disable interception; protocol stall between worker and Chromium exceeding REQUEST_INTERCEPTION_CLEANUP_TIMEOUT_MS.

Common situations: Scripts that block requests but hang a handler (e.g. awaiting a slow fetch inside the intercept handler); a wedged or overloaded Chromium; attached browser with pending network traffic.

Related errors


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