{"record":{"id":"e7779af9d60592b3","repo":"can1357/oh-my-pi","slug":"failed-to-clear-browser-request-interception-after","errorCode":null,"errorMessage":"Failed to clear browser request interception after browser.run","messagePattern":"Failed to clear browser request interception after browser\\.run","errorType":"exception","errorClass":"RequestInterceptionCleanupError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/browser/tab-worker.ts","lineNumber":640,"sourceCode":"\t\tasync cleanup() {\n\t\t\tif (onDescriptor) Object.defineProperty(page, \"on\", onDescriptor);\n\t\t\telse Reflect.deleteProperty(page, \"on\");\n\t\t\tif (offDescriptor) Object.defineProperty(page, \"off\", offDescriptor);\n\t\t\telse Reflect.deleteProperty(page, \"off\");\n\t\t\tif (onceDescriptor) Object.defineProperty(page, \"once\", onceDescriptor);\n\t\t\telse Reflect.deleteProperty(page, \"once\");\n\t\t\tif (removeAllDescriptor) Object.defineProperty(page, \"removeAllListeners\", removeAllDescriptor);\n\t\t\telse Reflect.deleteProperty(page, \"removeAllListeners\");\n\t\t\tfor (const handler of requestHandlers) Reflect.apply(off, page, [\"request\", handler]);\n\t\t\trequestHandlers.length = 0;\n\t\t\ttry {\n\t\t\t\tawait withTimeout(\n\t\t\t\t\tpage.setRequestInterception(false),\n\t\t\t\t\tREQUEST_INTERCEPTION_CLEANUP_TIMEOUT_MS,\n\t\t\t\t\t\"Timed out clearing browser request interception\",\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new RequestInterceptionCleanupError(\n\t\t\t\t\t\"Failed to clear browser request interception after browser.run\",\n\t\t\t\t\t{\n\t\t\t\t\t\terror: error instanceof Error ? error.message : String(error),\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t};\n}\n\nfunction errorPayload(error: unknown): RunErrorPayload {\n\tconst recoverTab = error instanceof RequestInterceptionCleanupError || undefined;\n\tif (error instanceof ToolAbortError) {\n\t\treturn { name: error.name, message: error.message, stack: error.stack, isToolError: false, isAbort: true };\n\t}\n\tif (error instanceof ToolError) {\n\t\treturn {\n\t\t\tname: error.name,","sourceCodeStart":622,"sourceCodeEnd":658,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/browser/tab-worker.ts#L622-L658","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Inspect the wrapped `error` field: fix the underlying cause (typically an un-settled request handler in the run script).","Ensure your interception handler never blocks indefinitely — always call request.continue()/abort()/fulfill().","Retry browser.run; transient protocol stalls usually clear on a fresh run.","If the browser is wedged, restart the browser/tab so a clean page is used for the next run."],"exampleFix":"// before\nawait page.setRequestInterception(true);\npage.on(\"request\", req => doAsyncWork(req)); // may hang\n// after\npage.on(\"request\", req => {\n  Promise.race([doAsyncWork(req), Bun.sleep(5000)]).finally(() => req.continue().catch(() => {}));\n});","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await browser.run(script);\n} catch (err) {\n  if (err instanceof RequestInterceptionCleanupError) {\n    logger.warn(\"interception cleanup failed\", { cause: err.data?.error });\n    await restartBrowser(); // clear wedged state\n  } else throw err;\n}","preventionTips":["Always settle request handlers with continue/abort/fulfill, even on error paths","Never await unbounded work inside an interception handler","Wrap handler bodies in a timeout"],"tags":["request-interception","cleanup","timeout","puppeteer"],"backgroundTag":"request-interception-cleanup-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}