Playwright: Frame was detached
Last verified
Error: frame.click: Frame was detachedWhat it means
The Frame object your code was using has been removed from the page. Frames include iframes and the main frame of a page. When an iframe element is deleted, replaced, or reloaded by its parent in a way that creates a new frame, every pending and future call on the old Frame object fails with this message. Navigation errors can show a related form, such as net::ERR_ABORTED; maybe frame was detached? or Navigating frame was detached!.
The pattern is the same as with element handles: you grabbed a reference to a specific frame instance (for example via page.frame() or elementHandle.contentFrame()), and the page swapped it out. Payment widgets, embedded login forms, and ad iframes are frequent offenders because they rebuild themselves.
What is not wrong: the selector inside the frame. The container disappeared underneath it.
What it looks like
// Fragile: Frame object can be detached by a re-render
const frame = page.frame({ url: /checkout/ });
await frame.fill('#card', '4242424242424242');
// Robust: re-resolved on every call
const card = page.frameLocator('iframe[title="Secure card input"]');
await card.getByLabel('Card number').fill('4242424242424242');Why it happens
- The parent page removed and re-created the iframe, for example a payment widget re-rendering after validation.
- A single-page app navigated and unmounted the component that held the iframe.
- Code stored a Frame object from page.frames() and used it after a page navigation.
- The iframe navigated to a URL that caused the browser to replace the frame.
How to fix it
- Use page.frameLocator('iframe[title="Payment"]') or locator.contentFrame(); these re-resolve the iframe on every action.
- Re-acquire Frame objects after any navigation instead of caching them.
- Wait for the iframe to be stable before interacting: await expect(page.locator('iframe[title="Payment"]')).toBeVisible().
- If the frame reloads as part of the flow, wait for the content you need inside the new frame rather than for the old one to respond.
How to stop it recurring
Never keep long-lived references to frames; address them by a stable attribute (title, name, src pattern) through frameLocator. Prefer locators throughout so both frames and elements are looked up fresh on each action. When a third-party widget is known to rebuild itself, assert on its final state before typing into it.
Official documentation: playwright.dev/docs/api/class-framelocator. See all Playwright error messages.
Related errors
- Element is not attached to the DOMError: elementHandle.click: Element is not attached to the DOM
- Execution context was destroyed, most likely because of a navigationError: page.evaluate: Execution context was destroyed, most likely because of…
- Target page, context or browser has been closedError: page.goto: Target page, context or browser has been closed
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 "Frame was detached" mean in Playwright?
The Frame object your code was using has been removed from the page. Frames include iframes and the main frame of a page. When an iframe element is deleted, replaced, or reloaded by its parent in a way that creates a new frame, every pending and future call on the old Frame object fails with this message. Navigation errors can show a related form, such as net::ERR_ABORTED; maybe frame was detached?
How do I fix "Frame was detached"?
1. Use page.frameLocator('iframe[title="Payment"]') or locator.contentFrame(); these re-resolve the iframe on every action. 2. Re-acquire Frame objects after any navigation instead of caching them. 3. Wait for the iframe to be stable before interacting: await expect(page.locator('iframe[title="Payment"]')).toBeVisible(). 4. If the frame reloads as part of the flow, wait for the content you need inside the new frame rather than for the old one to respond.
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.