Playwright: Execution context was destroyed, most likely because of a navigation
Last verified
Error: page.evaluate: Execution context was destroyed, most likely because of a navigationWhat it means
Every document has a JavaScript execution context. When the page navigates, reloads or a frame changes documents, the old context is thrown away. Any page.evaluate(), locator.evaluate() or handle-based call that was running in, or bound to, the old context fails with this message, because the code it was running and the objects it referenced no longer exist.
It usually shows up when an action triggers a navigation (a form submit, a redirect after login, a client-side reload) and the next line evaluates script before the new document is ready, or when a site performs a redirect chain on its own. With locators and auto-waiting actions it is rare, because those are retried in the new context automatically.
What is not wrong: your script logic. It ran against a page that disappeared halfway through.
What it looks like
// JavaScript
await page.getByRole('button', { name: 'Log in' }).click();
await page.waitForURL('**/dashboard');
const user = await page.evaluate(() => window.__USER__);
# Python
page.get_by_role("button", name="Log in").click()
page.wait_for_url("**/dashboard")
user = page.evaluate("() => window.__USER__")Why it happens
- Calling page.evaluate() right after a click that submits a form or follows a link.
- The site redirects after load (consent walls, login redirects, meta refresh).
- page.reload() or page.goto() running concurrently with an evaluate due to a missing await.
- Holding a JSHandle from before a navigation and using it afterwards.
How to fix it
- After an action that navigates, wait for the destination first: await page.waitForURL('**/dashboard') or an element on the new page.
- Start waiting for the navigation in parallel with the click so the race cannot be lost.
- Prefer locator methods (textContent, getAttribute, evaluate on a locator) that re-resolve in the current document.
- Add the missing await if two navigation-related calls overlap.
- For pages with unpredictable redirects, wait for load state ('domcontentloaded') before evaluating.
How to stop it recurring
Pair every navigating action with an explicit wait for the destination URL or element. Keep evaluate calls short and stateless so they can be safely re-run, and avoid passing handles across navigations. Most such flows can be written entirely with locators, which removes the problem.
Official documentation: playwright.dev/docs/navigations. See all Playwright error messages.
Related errors
Definitions
- PlaywrightPlaywright is Microsoft's open-source browser automation framework that provides a single API to control Chrom
- Chrome DevTools Protocol (CDP)The Chrome DevTools Protocol (CDP) is the JSON-over-WebSocket interface Chrome exposes for inspecting and cont
- CSS SelectorA CSS selector is a pattern used to identify and target specific HTML elements on a web page, widely used in b
- Headless ChromeHeadless Chrome is Google Chrome running without a visible window. It renders pages and runs JavaScript like n
- IframeAn iframe (inline frame) is an HTML element that embeds a separate web page within a parent page, creating an
- Web ElementA web element is any individual component rendered on a web page — buttons, links, input fields, images, text
Quick answers
What does "Execution context was destroyed, most likely because of a navigation" mean in Playwright?
Every document has a JavaScript execution context. When the page navigates, reloads or a frame changes documents, the old context is thrown away. Any page.evaluate() , locator.evaluate() or handle-based call that was running in, or bound to, the old context fails with this message, because the code it was running and the objects it referenced no longer exist.
How do I fix "Execution context was destroyed, most likely because of a navigation"?
1. After an action that navigates, wait for the destination first: await page.waitForURL('**/dashboard') or an element on the new page. 2. Start waiting for the navigation in parallel with the click so the race cannot be lost. 3. Prefer locator methods (textContent, getAttribute, evaluate on a locator) that re-resolve in the current document. 4. Add the missing await if two navigation-related calls overlap. 5. For pages with unpredictable redirects, wait for load state ('domcontentloaded') before evaluating.
Run browser automation you can watch and take over
Autonoly runs each job in a real cloud Chromium browser driven by Playwright. Timeouts and detached elements still happen; the difference is that you can watch the run live, see the step that failed, and take control of the browser to finish it.
Also see Live browser control.