Desktop preview snapshots time out after CDP relay reconnects#24812

opened17d agobyFfredrikbernholm

Problem

preview_snapshot repeatedly times out for an existing desktop preview tab, while HTTPS navigation and preview_evaluate continue to work. A minimal page with one heading and one button reproduces it, so it does not require a busy application or a certificate error.

The tool reports:

text
1Preview snapshot failed: Preview automation snapshot timed out after 15000ms.

The underlying server error is:

text
1The page was too busy to capture a snapshot in time. Wait for it to settle and take another snapshot.

Environment

  • T3 Code Beta 0.1.2
  • macOS 27.0.1, Apple Silicon
  • Also reproduced in an isolated Electron 44.9.3 guest using the current T3 CDP relay and ServerBrowserPage.snapshot
  • Playwright Core 1.60.0 in the isolated reproduction

Reproduction

  1. Create an Electron BrowserWindow with a temporary user-data directory, load <h1>Snapshot probe</h1><button>Test</button>, and attach its debugger.
  2. Bridge that debugger through createCdpRelayConnection and connect Playwright with chromium.connectOverCDP.
  3. Call ServerBrowserPage.snapshot with renderScale: "display". The first snapshot succeeds.
  4. Disconnect Playwright, preserving the Electron guest and its debugger attachment.
  5. Create another relay connection for the same guest and reconnect Playwright.
  6. Call the same snapshot operation. It times out. Raw Runtime.evaluate still succeeds.

Expected: both connections can snapshot the existing page and return its heading, button refs, and screenshot.

Actual: the first succeeds; the second reports the timeout above.

Findings

Electron retains enabled CDP domains across relay connections. If Runtime is already enabled, another Runtime.enable does not replay existing Runtime.executionContextCreated notifications. The new Playwright page therefore lacks its default execution context, and the page.evaluate portion of snapshot capture waits indefinitely. The generic busy-page timeout hides this distinction.

Resetting the native Runtime domain once before a new relay's first page-level Runtime.enable restored both snapshots in the isolated Electron reproduction. Child-target routing and subsequent enables in the same connection were left unchanged.

A regression test fails on the second connection without that reset and passes with it. All 14 relay/desktop-host tests and vp run check:changed passed for the candidate fix. Before/after Electron output:

text
1Original: round 1 passed, round 2 timed out
2Candidate fix: round 1 passed, round 2 passed
3Both successful captures included heading/button refs and a 900 × 568 PNG.

Related investigation and candidate fix: #24804. The running installation and its live data were not modified.

🤖 Posted by Codex (gpt-6.1-sol) on Fredrik's behalf

Synced from GitHub

Additional macOS symptom evidence from 26 October IST / 25 October UTC.

T3 Code Nightly 0.1.2-nightly.20261022.3512, Electron 44.9.3. A fresh tab explicitly using persistent profileId:"default" opened this repository successfully with open:false. Evaluation returned the expected URL/title, readyState:"complete", an Electron user agent, and an authenticated-site indicator.

preview_snapshot with includeImage:false failed:

text
1Preview snapshot failed: Preview automation snapshot timed out after 15000ms.

Evaluation still worked afterward. Presenting the same tab with open:true,show:true still reported visible:false. A second snapshot with includeImage:true,save:true failed identically; evaluation continued to work. The tab retained profileId:"default".

This confirms the snapshot/evaluation distinction on this installed macOS build. I did not observe or intentionally trigger a CDP relay reconnect, so this is not yet confirmation of the same cause. Hidden-tab capture, tracked in #23936, remains an alternative. No app restart or patch was performed, and #24829 has not been tested in this installation.

Posted by Codex at Osiris's request.

Synced from GitHub

Same symptom on Linux (Arch, Wayland, x64), T3 Code desktop AppImage 0.1.2 (server 0.1.2), Claude Code harness.

What the user did: an agent was driving a desktop preview tab. It called preview_resize (freeform 1440×1000), and snapshots kept working. The user then opened the same browser in the sidebar to watch, interacted with it (resizing and clicking), and from then on every preview_snapshot timed out. The browser tab itself kept working normally for the user. Only restarting the app fixed it.

Timeline from traces (local time):

  • 10:01: several snapshot/automation calls succeed (87–650 ms)
  • 10:01:22, 10:02:31: preview.resize RPCs
  • 10:04:51 and 10:04:53: desktop PreviewManager.registerWebview runs twice (webview re-registered)
  • 10:04:53 onwards: every preview_snapshot fails after ~10 000 ms with PreviewAutomationTimeoutError caused by "The page was too busy to capture a snapshot in time…". Six attempts over ~2 minutes all failed.
  • In between, preview_evaluate, preview_status, preview_navigate and preview_open succeed (2–130 ms)

The pattern matches this issue: a stale execution context after the page is re-attached, with evaluate unaffected. A minor separate point: the error text says "timed out after 15000ms", but the server-side snapshot gives up after 10 s (SNAPSHOT_TIMEOUT_MS = 10_000 in apps/server/src/preview/ServerBrowserPage.ts), so the message is misleading.

Possibly related: #24514 (off-window guests stall Page.captureScreenshot). The candidate fix #24804 was closed in favor of this issue, and the problem still reproduces on 0.1.2.

Investigated with t3 triage by Claude Code (Claude Opus 5.5).

Synced from GitHub

Note

Written by Claude Code (Claude Opus 5.5) on behalf of the reporter, after investigating on their machine.

Same signature on macOS 27 / Apple Silicon, T3 Code (Beta) 0.1.2, Playwright 1.60.0, Electron 44.9.3. preview_evaluate and preview_navigate work, while preview_snapshot times out.

In our case no relay reconnect was involved. It failed on brand-new tabs and again after a full app restart, and every tab reported visible:false. Keeping server-driven guests inside the compositor viewport fixed it locally: a one-line change in HostedBrowserWebview, with details in #23936. That points our case to the hidden-guest cause rather than a stale context after reconnect. The reconnect case described here may still be a separate bug.

The timeout message says 15000ms, but the server-side snapshot gives up after about 10 s.