fix(cli): avoid hanging on unresponsive tab titles#41733
Conversation
There was a problem hiding this comment.
Pull request overview
This PR hardens Playwright CLI tab header rendering so it won’t hang when an attached CDP tab becomes discarded/unresponsive and never answers renderer-bound calls like page.title().
Changes:
- Add a 5s cap around
Tab.headerSnapshot()title lookup so one unresponsive tab can’t block response rendering. - Add an MCP test that simulates an unresponsive tab (blocked main thread) and asserts
browser_tabslisting still completes and renders the tab with an empty title fallback.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
packages/playwright-core/src/tools/backend/tab.ts |
Adds a timeout-guarded title collection in headerSnapshot() to prevent CLI response rendering from hanging on unresponsive tabs. |
tests/mcp/tabs.spec.ts |
Adds coverage ensuring browser_tabs listing is not blocked by a tab whose title lookup never resolves. |
| // resolve the title lookup. Cap it so that one bad tab does not block | ||
| // rendering of the whole response. | ||
| let timeoutId: ReturnType<typeof setTimeout> | undefined; | ||
| const titleTimeout = new Promise<void>(resolve => timeoutId = setTimeout(resolve, 5000)); |
There was a problem hiding this comment.
We don't want to rely on a timeout for this, as it would be unreliable on a slow machine, page hanging on load etc. Also it only addresses title command while any other interaction with the frozen page will lead to an error. We are going to try to find a better fix that can be applied on the browser side to help playwright reliably detect unresponsive/frozen tabs when connecting over CDP and not fail on them.
|
Closing this pr. Stay tuned for the updates in the issue. |
Summary
Prevents Playwright CLI response rendering from hanging when one attached CDP tab is discarded or unresponsive.
Why
Tab.headerSnapshot()currently waits onpage.title()while building tab headers. If one tab never resolves renderer-bound calls, response rendering can block while collecting headers for all tabs, causing unrelated CLI commands to time out.This intentionally does not change
connectOverCDPinitialization behavior. It only guards CLI response rendering so one unresponsive tab header cannot block unrelated commands after the connection has already succeeded.Change
Adds a narrow timeout/catch around tab title collection so an unresponsive tab falls back to the existing empty-title path instead of blocking the whole response.
Tests
npm run ctest-mcp tabs.spec.ts -- --grep "unresponsive tab"npm run ctest-mcp tabs.spec.tsReferences #41714.