You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
playwright-cli attach hangs forever: Tab.headerSnapshot awaits page.title() without a timeout on a half-initialised page #489
@playwright/cli 0.1.22 with playwright-core 1.64.1 (also seen with 0.1.21 / playwright-core 1.64.0-alpha). Chromium 154 on Linux. Code unchanged on microsoft/playwright main at b4695e3eb2.
Steps to reproduce
Start Chromium with --remote-debugging-port=9222 and use it normally, with many tabs (here 28). In our case a hidden tab that had been reloaded ended up in this state; we have no deterministic way to create it from scratch.
Run playwright-cli -s=s attach --cdp=http://127.0.0.1:9222.
Expected
Attach completes, listing the tabs. A tab that cannot report its title is listed without one.
Actual
attach never returns. The session daemon stays registered, and every later command (even run-code 'async page => 1') queues behind it and hangs too, until the session is detached.
Analysis
CDP is fine: chromium.connectOverCDP connects in 0.6–0.8 s, and with DEBUG=pw:protocol all 641 CDP requests of the attach got answers.
With DEBUG=pw:channel, the one call that never returns is frame.title().
Tab.headerSnapshot() (packages/playwright-core/src/tools/backend/tab.ts) runs on attach and after every command, for every tab, and awaits this.page.title() with no timeout:
For the blocking tab, Playwright's main frame is half-initialised: page.url() is "" and the frame's load states are only ["commit"]. So title() waits forever for a main-world execution context. The same tab is fine over raw CDP: Runtime.evaluate answers in about 1 ms, Page.getFrameTree works, readyState is complete, and the tab is not discarded or prerendering.
We bound the call: 3 s for the first wait, then 100 ms per later snapshot while the same pending title() is still unresolved, and leave the title empty. With it, attach takes 3.7 s instead of hanging, later commands take 0.3 s, and the tab is listed as - 6: [](). Unpatched, the same browser times out at 60 s every time.
Suggestion
Bound title() in headerSnapshot() (a small change; PR to follow in microsoft/playwright). Separately, the frame never leaving the "commit"/url "" state while the renderer is loaded may be a bug in frame tracking after connectOverCDP; we can collect a pw:protocol log for that tab if it helps.
cyppe Any chance you can dump the contents of chrome://discards and chrome://process-internals (all three tabs there) next time this happens? We really need to figure out what's the state of the page that prevents attach from completing, to figure out a long-term solution.
Hi, I'm the Playwright bot. I tried to reproduce this on Linux.
I could not recreate the half-initialized frame, on current main or with playwright-core 1.64.1. With 28 tabs, background reloads and frozen tabs, attachment and later commands completed. A coverage test for attachment after a background-tab reload is proposed; it does not fix or simulate the reported missing execution context.
One relevant detail: page.title() evaluates in Playwright's utility world, not the default world used by bare CDP Runtime.evaluate. A successful default-world evaluation does not establish that the utility-world context was initialized. The timeout patch in microsoft/playwright#43620 was closed without merging, so I have not repeated it.
Could you share a sanitized DEBUG=pw:protocol,pw:channel log starting before the failing attach, together with the chrome://discards and chrome://process-internals dumps requested above? The missing piece is a way to create, or inspect initialization of, the affected frame.
What I ran
All runs were on Linux. Each probe used 28 tabs and checked all titles after CDP connection, with a five-second bound on title collection. Variations were ordinary loaded tabs, a frozen background tab, reload while frozen, thawing that tab, and 20 reload/connection races.
For upstream Chrome, the pinned core, and core 1.64.1, I also disabled the original session's focus emulation and confirmed document.hidden === true on the background tab before testing. In the four non-race states, actual CLI attach, tab-list, and run-code 'async page => 1' all completed and returned the expected titles/result. No probe produced the reported empty-URL frame.
The reporter's Chromium 154 and long-running browser profile were not available. These results do not establish that the bug is fixed.
The existing attach via cdp test now includes the background reload and checks attachment metadata, a snapshot, and a later run-code result. cli-cdp.spec.ts and cli-endpoint.spec.ts passed across the Chrome, Chromium, Firefox, and WebKit projects: 42 passed, 14 skipped. CDP-only cases are skipped for Firefox and WebKit. Build and the full npm run flint check passed.
Condensed scenario covered by the proposal
Using the repository's cdpServer, cli, and server fixtures:
Activity
dgozman commentedon Oct 26, 2026
cyppe Any chance you can dump the contents of
chrome://discardsandchrome://process-internals(all three tabs there) next time this happens? We really need to figure out what's the state of the page that preventsattachfrom completing, to figure out a long-term solution.github-actions commentedon Oct 31, 2026
github-actions commentedon Oct 31, 2026
Hi, I'm the Playwright bot. I tried to reproduce this on Linux.
I could not recreate the half-initialized frame, on current main or with
playwright-core1.64.1. With 28 tabs, background reloads and frozen tabs, attachment and later commands completed. A coverage test for attachment after a background-tab reload is proposed; it does not fix or simulate the reported missing execution context.One relevant detail:
page.title()evaluates in Playwright's utility world, not the default world used by bare CDPRuntime.evaluate. A successful default-world evaluation does not establish that the utility-world context was initialized. The timeout patch in microsoft/playwright#43620 was closed without merging, so I have not repeated it.Could you share a sanitized
DEBUG=pw:protocol,pw:channellog starting before the failingattach, together with thechrome://discardsandchrome://process-internalsdumps requested above? The missing piece is a way to create, or inspect initialization of, the affected frame.What I ran
All runs were on Linux. Each probe used 28 tabs and checked all titles after CDP connection, with a five-second bound on title collection. Variations were ordinary loaded tabs, a frozen background tab, reload while frozen, thawing that tab, and 20 reload/connection races.
1.65.0-next,a6fb02f5aa494764a21a637f2db6ea1031461935158.0.8127.2156.0.8078.470.1.22, pinned core1.64.0-alpha-1790635538000, upstreame8149b8257d32dcf8f72573ecc43e72439da7080155.0.8059.120.1.22, core1.64.1, upstreamcfe490d941f992655948eee8fd4fd94e1c4234bf156.0.8078.47For upstream Chrome, the pinned core, and core 1.64.1, I also disabled the original session's focus emulation and confirmed
document.hidden === trueon the background tab before testing. In the four non-race states, actual CLIattach,tab-list, andrun-code 'async page => 1'all completed and returned the expected titles/result. No probe produced the reported empty-URL frame.The reporter's Chromium 154 and long-running browser profile were not available. These results do not establish that the bug is fixed.
The existing
attach via cdptest now includes the background reload and checks attachment metadata, a snapshot, and a laterrun-coderesult.cli-cdp.spec.tsandcli-endpoint.spec.tspassed across the Chrome, Chromium, Firefox, and WebKit projects: 42 passed, 14 skipped. CDP-only cases are skipped for Firefox and WebKit. Build and the fullnpm run flintcheck passed.Condensed scenario covered by the proposal
Using the repository's
cdpServer,cli, andserverfixtures:This passes today. It covers the background-reload setup, not the unknown trigger that leaves a frame without an execution context.
Draft PR: microsoft/playwright#43816
Triaged on Linux by the Playwright bot - agent run