{"record":{"id":"3f2335944863630e","repo":"puppeteer/puppeteer","slug":"execution-context-was-destroyed-most-likely-becau","errorCode":null,"errorMessage":"Execution context was destroyed, most likely because of a navigation.","messagePattern":"Execution context was destroyed, most likely because of a navigation\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/puppeteer-core/src/bidi/util.ts","lineNumber":189,"sourceCode":"    if (error instanceof ProtocolError) {\n      error.message += ` at ${message}`;\n    } else if (error instanceof TimeoutError) {\n      error.message = `Navigation timeout of ${ms} ms exceeded`;\n    }\n    throw error;\n  };\n}\n\n/**\n * @internal\n */\nexport function rewriteEvaluationError(error: unknown): never {\n  if (error instanceof Error) {\n    if (\n      error.message.includes('ExecutionContext was destroyed') ||\n      error.message.includes('Inspected target navigated or closed')\n    ) {\n      throw new Error(\n        'Execution context was destroyed, most likely because of a navigation.',\n      );\n    }\n  }\n  throw error;\n}\n","sourceCodeStart":171,"sourceCodeEnd":196,"githubUrl":"https://github.com/puppeteer/puppeteer/blob/d484e21c17f6023826fefdcdeeb553e04a7aaed8/packages/puppeteer-core/src/bidi/util.ts#L171-L196","documentation":"rewriteEvaluationError catches the browser's raw 'ExecutionContext was destroyed' / 'Inspected target navigated or closed' messages and rewrites them into a human-readable form. It fires whenever a script evaluation runs against a realm/frame that no longer exists — almost always because the page navigated or was closed between scheduling and executing the function.","triggerScenarios":"Calling page.evaluate / frame.evaluate / elementHandle.evaluate while a navigation is in flight; clicking an element whose handler triggers navigation, then awaiting a subsequent evaluate on the old context; awaiting evaluate after page.close().","commonSituations":"Race between a click that navigates and the next evaluate; SPA route changes that destroy the frame; reusing an ElementHandle after a navigation; calling evaluate on a frame whose page just redirected.","solutions":["Re-acquire the page/frame handle after navigation before evaluating (waitForNavigation / waitForFunction).","Use page.waitForFunction with the desired predicate instead of evaluate-after-click.","Detect the navigation race and retry the evaluate on the new context.","Avoid keeping ElementHandle references across navigations."],"exampleFix":"// before\nawait button.click(); // triggers navigation\nawait page.evaluate(() => document.title);\n// after\nawait Promise.all([\n  page.waitForNavigation(),\n  button.click(),\n]);\nawait page.evaluate(() => document.title);","handlingStrategy":"retry","validationCode":"// Acquire fresh context after navigation\nawait page.waitForNavigation();\nawait page.evaluate(fn);","typeGuard":"const isContextDestroyed = (e) => e instanceof Error && /Execution context was destroyed/i.test(e.message);","tryCatchPattern":"try { return await page.evaluate(fn); } catch (e) { if (isContextDestroyed(e)) { await page.waitForFunction(fn); return; } throw e; }","preventionTips":["Pair click+navigation with waitForNavigation.","Never reuse ElementHandles across navigations.","Prefer waitForFunction over evaluate-after-action."],"tags":["bidi","evaluation","navigation","race-condition"],"backgroundTag":null,"analyzedSha":"d484e21c17f6023826fefdcdeeb553e04a7aaed8","analyzedAt":"2026-08-12T06:33:19.665Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}