[Bug]: Windows snapshot/evaluate timeouts evict the shared server-browser host and abort another open#16921

opened16d agobyHhogeheer499-commits

Scope correction — 15 October 2026: #16941 no longer fixes shared-host eviction. It only skips expired queued agent work (recordingStop exempt). It does not cancel running operations or fix Cloudflare verification. Host retention is proposed separately in #17871. Earlier #16941 scope/test claims below refer to the superseded broader revision; see the current PR description for the narrowed scope and verification.


Before submitting

  • I searched existing reports, including #16264, #16779, #12778, #16596, and #5002. This adds Windows .2735 ordinary-page evidence and a trace of one timeout aborting a separate open request. I am not claiming a newly established root cause for every symptom; please consolidate with an existing report if appropriate.
  • I included the observed operation sequence, release commits, sanitized traces, successful retests, and limits of the investigation.

Area

apps/server / preview automation broker and server browser, with the Windows desktop/native-rendering path also involved.

Summary (original 7 October report)

On Windows 11, T3 browser snapshots and evaluations timed out after 15 seconds on example.com, even after recreating the tab and downgrading from .2774 to exact .2735. The timeout disconnected the shared automation host; the following click/status calls returned "No preview automation host is available".

During a later investigation, a snapshot already in flight timed out and disconnected server-browser, causing a different open request to fail after only about 6.5 seconds. The host registered again roughly one second later. This cascade is visible in the local traces and matches the broker implementation.

The original snapshot stall remains unexplained. The browser is intermittently usable: a later fresh .2735 tab, verified as Windows Chrome headless shell 154, successfully completed DOM reads, a snapshot, and a link click. Cloudflare verification remained blocked in that engine. Earlier Windows Cloudflare failure used native Electron/Chromium 152, so these should not be treated as a single proven engine-specific defect.

Latest live retest — 10 October 2026

Tested the unpatched official 0.0.46-nightly.20261010.2922 (bd2346eda). PR #16941 is still unmerged and was not installed. This tab actually ran on Windows Chrome headless shell 154.0.8037.92 (Chrome/154, Win32, navigator.webdriver === false), not the app's Electron 44.4.5 / embedded Chromium 152.0.7977.130 renderer.

CheckResult
Ordinary open/navigation, DOM evaluation and text snapshotsPassed on example.com and an isolated local test page.
Snapshot-ref clicking, typing and background PNG savePassed; counter and typed text verified, saved image visually inspected.
Deliberate 300 ms navigation timeoutExpected timeout after 346 ms; host and same-tab navigation/snapshot recovered.
Unresolved evaluationExpected timeout after 15,055 ms; same-tab evaluation recovered in 46 ms.
Concurrent other-tab requestA 25-second wait completed after 17,116 ms while the first tab's evaluation timed out; no host-loss error. Later snapshot/ref click also worked.
Fresh incognito Cloudflare loginStill showed There was a problem with verification. Please reload and try again. with Sign in disabled.
Normal Cloudflare reloadReached Just a moment... / Performing security verification instead, with a human-verification checkbox visible in the saved screenshot.
Cloudflare snapshotsThree settled-login attempts returned The page changed while capturing its snapshot. Take another snapshot.. Evaluation and cookie-banner dismissal still worked. A challenge-page PNG succeeded after reload.

The original ordinary-page 15-second snapshot failure and missing-host cascade were not reproduced in this retest. Current upstream's evaluation termination and response grace are present in this release. These successful normal typed-timeout paths do not establish recovery from a genuinely unanswered read/capture stage beyond the grace period or cancellation of expired queued/active work; those remain covered by PR #16941's code and regression tests.

Cloudflare verification remains unresolved in this fresh headless session. Initial 403 responses were observed at /cdn-cgi/zaraz/t; their relationship to verification failure is unknown, and the earlier origin-warning cause was not re-established. The page-change snapshot errors did not turn into a 15-second hang or host eviction. No challenge was solved, no credentials entered, and no sign-in attempted. Manual Take control, native Electron hidden capture and native macOS were not retested. The original evidence below remains historical evidence, not a claim that every symptom persists on nightly 2922.

Steps to reproduce

This is the recorded intermittent sequence; a later fresh headless tab succeeded.

  1. On Windows T3 .2735, call preview_status, then preview_open and navigate to https://example.com.
  2. Navigation succeeds, with title Example Domain and loading: false.
  3. Call preview_snapshot({tabId, includeImage:false}). The recorded call times out after 15,000 ms.
  4. Close that tab through t3_preview_close and open a fresh tab at the same URL with reuseExistingTab:false.
  5. A small evaluation of document.title and the first link succeeds once.
  6. Another snapshot times out after 15,000 ms. Evaluating body text and links then times out too.
  7. The next click on the IANA link is rejected with the missing-host error. An immediate status call is rejected too.

The later cascade was captured while another snapshot was pending. A new preview_open request overlapped it and failed when that snapshot's deadline disconnected the shared host. This was not an open request reaching its own timeout.

Expected behavior

Successful navigation should leave ordinary page inspection and interaction usable. A slow snapshot or evaluation should not take out unrelated requests on a healthy shared in-process browser host. If a host is recovering, the error should describe that temporary state accurately.

Preserve the existing protection against replaying an action whose effects are uncertain. No automatic replay of clicks or other mutations is requested.

Actual behavior and trace evidence

All times are UTC on 7 October 2026; Amsterdam local time was UTC+2. Individual environment, thread, session, tab, and trace identifiers have been omitted.

Time UTCRecorded event
17:33:56Navigation to Example Domain succeeds
17:34:12.208–17:34:27.214Broker waits about 15,005 ms for the first snapshot, then returns a timeout
17:34:27.213disconnect / closeConnection
17:34:28.223Host connects again
17:36:27Old tab closed and fresh tab opened
17:36:41Evaluation returns the title and IANA link
17:36:49.413–17:37:04.425Fresh-tab snapshot times out after about 15,012 ms
17:37:04.425Host disconnected again
17:37:05.432Host connects again
17:37:18.315–17:37:33.316Evaluation times out after about 15,001 ms
17:37:33.316Host disconnected; following click/status cannot find a host
17:37:34.327Host connects again
17:50:19Later status reports the tab available; complete recovery was not tested at that point
19:33:14.824Another snapshot starts waiting for a broker response
19:33:23.342A separate open request starts waiting
19:33:29.826disconnect / closeConnection; the pending open fails after 6,484 ms with server-browser disconnected during open
19:33:29.842The snapshot's failed span finishes at about 15,018 ms
19:33:30.852Host connects again

The Windows app processes remained running. Process existence alone would not establish browser health, but the disconnection/re-registration sequence above is independently visible in server traces.

Relevant exact errors:

text
1Preview automation snapshot timed out after 15000ms.
2Preview automation evaluate timed out after 15000ms.
3Preview automation client server-browser disconnected during open.
json
1{
2 "error": {
3 "_tag": "PreviewAutomationTimeoutError",
4 "operation": "snapshot",
5 "failureCount": 1,
6 "message": "Preview automation snapshot timed out after 15000ms."
7 }
8}

The subsequent click error, with the environment identifier replaced, was:

text
1No preview automation host is available for click in environment [ENVIRONMENT_ID]. Preview tools run in a T3 Code desktop app that is open and connected to this environment; a headless server has no browser of its own. Do not retry. To check a page, use a headless browser from the shell, such as Playwright, or curl, or ask the user to open this thread in the T3 Code desktop app.

A corresponding for status error followed. No click was performed in that failed test.

Source findings and investigation limits

Release .2735 resolves to fd1c3386c4d60f3477ab3f13c87537848de099f5; .2774 resolves to 611132c171f3a821bd2e32f22261135cef6330ac.

  1. Why other requests get disconnected is established. In PreviewAutomationBroker.ts, an unanswered primary request disconnects its connection. closeConnection fails the other pending requests on that connection. This explains the captured cascade, not the initial stall.
  2. The existing recovery does run. ServerBrowser's host loop reconnects after one second; the traces agree. #12535 is already merged. This is not simply the older permanently-unregistered-host problem.
  3. includeImage:false does not bypass image capture. The MCP handler strips output-selection options. ServerBrowserPage.snapshot still waits concurrently for page evaluation, a boxed accessibility snapshot, and Page.captureScreenshot. The stalled branch has not been isolated. The accessibility timeout and broker deadline are both 15 seconds; whether a deadline race contributed here is unproven.
  4. runtime:server does not identify the rendering engine. ServerBrowser's native-attachment path waits up to ten seconds for its desktop page and otherwise uses headless Chromium. The app's Electron version alone cannot identify a tab's engine.

Possible maintainer directions are to bound/diagnose individual snapshot stages, cancel or retire the affected operation/tab without evicting unrelated healthy work, and distinguish a recovering host from a genuinely absent one. These are suggestions, not an implemented or verified fix.

The latest release available when checked was .2787 (f570bd21663f56ce94c41829d3b7d72886e25a34). Its broker, server browser, snapshot implementation, and CDP relay files were byte-identical to .2735; its Electron host component differed. .2787 was not installed or tested, so no claim is made that upgrading cannot help.

Successful retest and remaining Cloudflare failure

At 19:45–19:47 UTC, without applying a source patch or another version change, a fresh Windows .2735 tab completed:

  • DOM reads, including body textContent and innerText;
  • a full snapshot, with accessibility refs and an internally captured PNG;
  • a click using the snapshot-provided ref for Learn more, reaching the IANA example-domains page.

The tab reported runtime:server; its page user agent was:

text
1Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/154.0.8037.92 Safari/537.36

navigator.webdriver was true. The Windows Chrome headless shell process and version were independently checked. This establishes recovery of basic automation on that engine; it does not identify why the original tab stalled or prove native Electron recovery.

Opening a fresh https://dash.cloudflare.com/login tab at 19:47:54 UTC still reached Just a moment.... At 19:48:24 it showed security verification, readyState:complete, no Sign in button, a 403 resource error, and No available adapters. warnings. At 19:51:42 it was still at security verification without a Sign in button. Snapshot inspection remained usable. No challenge was solved, credentials entered, identity altered, or session data transferred.

Cloudflare's supported-browser documentation describes limited support for embedded browsers and excludes automated browsers from production challenge solving. This provides compatibility context for the headless failure, not a diagnosis of the earlier native Electron failure.

Impact

Major degradation: the Cloudflare email-forwarding workflow could not be completed through T3's browser, and ordinary page automation also failed intermittently. A practical fallback eventually worked in an existing signed-in external Chrome session.

Version and environment

ComponentVerified details
Windows OSWindows 11 Pro x64; 10.0.26200, build 26200
CPU / RAMRyzen 5 3600, 6 cores / 12 threads; 32 GiB RAM
GPU / driverRadeon RX550/550 Series; driver 31.0.21924.61
MotherboardB450M-HDV R4.0
Windows T3 app runtimeElectron 44.4.2, Chromium 152.0.7977.130, Node 24.21.0
Later Windows server browserChrome headless shell 154.0.8037.92
AgentCodex through T3 Code
Earlier remote Linux machineUbuntu 24.04.5 LTS x86_64; kernel 7.0.0-31-generic; Ryzen AI MAX+ 395 / Radeon 8060S; 32 logical CPUs

Earlier symptoms and all attempted workarounds

Initial Linux sandbox problem, native Windows Cloudflare failure, control tests, downgrade, and external Chrome errors

Ubuntu .2752: At 12:10 and 12:15 UTC, browser open failed with the explicit Ubuntu AppArmor sandbox message. Running the official version-specific t3 browser setup with sudo fixed startup. Setup allowed /etc/apparmor.d/t3-chrome-headless-shell with user-namespace permission; the global restriction remained enabled, and missing libraries were not found. Subsequent open and snapshot succeeded. This startup problem is resolved.

Cloudflare's Verify you are human still did not complete when I used Take control and clicked manually. After releasing control, status reported the agent as owner, but snapshot/evaluation timed out after 15 seconds. Closing the stuck tab and opening a fresh one restored ordinary reads and agent interaction temporarily.

A first button test injected into a blank tab was readable/clickable by tools, but the visible pane stayed on T3's start screen because the tab had no actual URL. This was a test-setup mistake. Serving a real localhost HTTP button page corrected it, and I confirmed manual clicking worked. Cloudflare verification still failed afterward. Agent calls while I retained control were correctly rejected; later timeouts also occurred after control returned to the agent.

One subsequent Linux close attempt returned OrchestratorMcpFailure, code orchestration_error, message The operation could not be completed. A fresh open on the official Cloudflare login URL succeeded but remained at the challenge.

Windows .2774: At 12:57 UTC, the Cloudflare login capture logged a generic 403 and 19 repetitions of:

text
1Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('https://challenges.cloudflare.com') does not match the recipient window's origin ('https://dash.cloudflare.com').

The visible error was There was a problem with verification. Please reload and try again. Reloading by navigating to /login did not resolve it. DOM inspection confirmed Sign in was visible and disabled. navigator.webdriver was false, and the user agent included T3Code(Nightly)/0.0.46-nightly.20261007.2774 Chrome/152.0.7977.130 Electron/44.4.2. This was native Electron, not the later headless-154 retest.

The snapshot's interactiveElements list and a later iframe query were empty. The generic 403 was not correlated to a particular request, and the origin warning's source/frame was not traced. None establishes the exact verification cause or an iframe-removal bug.

Downgrade: Windows was replaced/restarted on exact .2735; installer signature, official asset checksums, executable/install version, running app, and T3 environment version were checked. The active Linux backend and installed AppImage link were changed to .2735, with backups and endpoint health checks. Older unrelated Linux processes were outside the active backend route and were not all restarted. A fresh Linux preview after the downgrade was not tested. HTTP backend reachability is not browser-health evidence. The Windows ordinary-page failures described above persisted; they do not prove the identical native Cloudflare console failure on .2735.

External Chrome: The offered old t3_fastpc.browser_tabs route failed with McpServerError: Tool browser_tabs not found (INVALID_ARGUMENT, JSON-RPC -32602). The supported bundled chrome@openai-bundled plugin 26.908.40834, bootstrapped through documented setupBrowserRuntime() in node_repl, worked. Existing signed-in Cloudflare tabs were readable/clickable and the email-forwarding task completed.

In a later Chrome task, the Windows computer-use route returned codex app-server exited before returning response 1 three times. Two tab.screenshot(...) attempts, including a smaller clip, failed with Timed out after 5000ms waiting for CDP command Page.captureScreenshot. The same Chrome session remained reachable; tab.ax.get('screenshot') produced usable screenshots. These are separate route-specific observations, not proof of a shared T3 preview cause. A script-variable error and a separate approval-layer rejection were also excluded from browser-failure diagnoses.

The external Chrome comparison reused a logged-in profile; a controlled fresh challenge test with matching profile/cookies/network was not performed. It is a practical workaround rather than proof of a native Electron fix.

Related reports and proposed fixes

  • #16264 covers a timed-out evaluation continuing and temporarily making other preview tools unavailable. This report supplies ordinary-page Windows snapshot evidence and the pending-open cascade in the newer server-browser path.
  • #16779 reports .2735 loading/iframe issues and a timeout cascade on macOS. No injected iframe or stuck loading-bar trigger was established in this Example Domain test.
  • #12778 is an older Windows .0.0.42 missing-host report. Its metadata-timeout proposal #14552 does not explain the recorded primary 15-second snapshot/evaluation deadlines; .2735 already avoids eviction for its optional metadata read.
  • #5002 was the older native-preview Turnstile loop. Its native-user-agent fix #7110 is merged; the .2774 failure above already retained the native Electron user agent.
  • #16596 reports a newer headless Cloudflare failure. Its proposed native-host synchronization fix #16620 was still unmerged when checked. It reports a successful anonymous login-page test on macOS, but has not been tested here and does not establish a fix for the earlier native Windows failure.
  • #15965 addresses batched requests lost in the older web-client stream consumer. The .2735 preferred server browser consumes requests directly through Stream.runForEach; its applicability to these failures is unproven.

There is no verified complete fix from this investigation. Resolved sandbox startup, intermittent basic-automation recovery, a working external Chrome fallback, and upstream candidate fixes should be distinguished from a repaired T3 Cloudflare workflow.

Note

Grok responding on behalf of Julius.

Triage

Confirmed on main (0678e4e23d86): one timed-out call on the server's own browser evicts the whole server-browser host, which fails every other in-flight preview call in the environment, including an unrelated preview_open. The first snapshot stall itself is not explained here. It looks like #16567.

What the code does

  1. A timeout on any call evicts the shared host. When a call gets no answer before its deadline, the broker calls disconnect(..., true) (PreviewAutomationBroker.ts#L654-L665). Only the background metadata read is exempt. removeConnectionFromState drops every pending request and every session's host assignment on that connection (#L140-L162), and closeConnection fails each pending request with PreviewAutomationClientDisconnectedError (#L359-L379). That error's message is "Preview automation client server-browser disconnected during open." (previewAutomation.ts#L1060).
  2. The host is one connection shared by the whole environment. The server browser registers once, with a fixed clientId and preferred: true (ServerBrowser.ts#L2150-L2181), and preferred hosts are picked first (PreviewAutomationBroker.ts#L548-L556). So one tab's 15s snapshot timeout fails other tabs' and other threads' requests that are still in flight. That includes an open on this host, whose 660s budget for a first-time Chromium install (#L562-L565) doesn't protect it from someone else's 15s deadline. Until the host loop registers again after HOST_RECONNECT_DELAY (1s, ServerBrowser.ts#L88), new calls get PreviewAutomationNoAvailableHostError, whose message says "Do not retry" (previewAutomation.ts#L898).
  3. Eviction doesn't stop the server-side work. handleRequest wraps runOperation in Effect.tryPromise with no abort signal and runs in a forked fiber (ServerBrowser.ts#L1706-L1731, #L2162-L2170). Its later reply is thrown away because the request is no longer pending under that connection (PreviewAutomationBroker.ts#L480-L493). For an evicted open, the tab can still be created on the server after the caller has already been told the call failed.
  4. A stalled snapshot keeps holding its tab. Snapshot and evaluate run in the tab's SessionControl queue (ServerBrowser.ts#L1605-L1617), and that queue has no per-action timeout (SessionControl.ts#L37-L44). evaluate sends Runtime.evaluate without a timeout (ServerBrowserPage.ts#L413-L418). A later evaluate on the same tab waits behind the stuck snapshot, which fits the 17:37:18 evaluate timeout that followed the fresh tab's snapshot timeout.

The reporter's two hypotheses

  • includeImage: false still takes a screenshot: confirmed. The MCP handler removes includeImage and save before forwarding (handlers.ts#L211-L215). ServerBrowserPage.snapshot always runs page.evaluate, ariaSnapshot and captureViewport together (ServerBrowserPage.ts#L191-L200), and captureViewport sends a bare Page.captureScreenshot (#L170-L174).
  • Equal deadlines: confirmed, but there's no real race. ariaSnapshot uses DEFAULT_TIMEOUT_MS = 15_000 (ServerBrowserPage.ts#L66), and snapshot gets the broker default of 15000ms. The broker's clock starts first, before the request is handed off and before any wait in the tab queue. So the broker always fires first, and ariaSnapshot's own timeout can never get back to the caller. The page.evaluate and screenshot branches have no timeout at all.

Not confirmed

  • Why the first snapshot on example.com stalled on Windows. #16567 shows a desktop-rendered background tab whose Page.captureScreenshot never settles. The report doesn't say whether the stalled tab was desktop-rendered or headless (the later working tab was headless), so this may or may not be the same trigger.

Fix direction

  • Don't evict the in-process server-browser host when a call times out. It isn't unreachable, so fail only the call that timed out and leave the connection, the other pending requests and the session assignments alone.
  • Bound each snapshot stage (especially Page.captureScreenshot) and Runtime.evaluate below the broker deadline, and release the tab's SessionControl slot when the broker gives up. This overlaps with #16567.
  • Optionally, skip the screenshot when includeImage: false.

Related

  • #16567 (open): the same unbounded snapshot and stuck tab queue, on macOS background tabs. Fixing it would remove this trigger but wouldn't stop a timeout from evicting the host.
  • #16264, #16764, #12898, #12273, #12319, #16779 (open): other timeouts that evict the host, mostly on the desktop host. This report adds the in-process server host and the in-flight open failure.
  • #15965 and #14084 (open PRs) only change the desktop web host (apps/web). The server browser consumes requests directly through Stream.runForEach, so neither covers this. #16620 (open PR) changes which engine renders a server tab, not the eviction or snapshot bounds. #12899 and #12279 exempt only waitFor misses and metadata reads.
  • The Cloudflare challenge failures are out of scope here and are tracked in #16596 (with #5002 closed).
Synced from GitHub

Scope correction — 15 October 2026: #16941 no longer fixes shared-host eviction. It only skips expired queued agent work (recordingStop exempt). It does not cancel running operations or fix Cloudflare verification. Host retention is proposed separately in #17871. Earlier #16941 scope/test claims below refer to the superseded broader revision; see the current PR description for the narrowed scope and verification.

Original update (historical scope)

Submitted #16941 on top of your merged child-frame fix #16939. It retains the in-process host on per-request timeouts, binds execution and queued cancellation to the original request lifetime, bounds browser reads, and skips capture for text-only snapshots unless saving a PNG.

181 focused tests pass, including real Chromium tests. The additional Windows check uses Electron 44.4.2 / Chromium 152.0.7977.130 with actual T3 browser code and the merged relay: text-only inspection/clicks work on a hidden guest, and timed-out capture/evaluation leaves the same tab usable. Independent review identified two deadline/cancellation gaps that were fixed before submission; the cancelled-click case was reproduced before its fix.

The PR documents the remaining limit: a fully hidden native guest can still fail PNG capture, but the timeout is bounded. It does not duplicate the child-frame fix or claim a verified Cloudflare login on the original account.

Synced from GitHub

Same host-eviction chain on macOS, so this isn't specific to Windows.

Environment: T3 Code Nightly 0.0.46-nightly.20261008.2819 (5e2225671f70), macOS 27.0 arm64, desktop app with a local server, Claude Code and Codex threads.

Server trace, 2026-10-08 (local time):

109:49:20 PreviewAutomationBroker.invoke PreviewAutomationTimeoutError: Preview automation evaluate timed out after 15000ms.
209:49:35 PreviewAutomationBroker.disconnect (x2)
309:49:36 PreviewAutomationBroker.connect / focusHost
409:49:41 PreviewAutomationBroker.invoke PreviewAutomationTimeoutError: Preview automation navigate timed out after 15000ms.
509:49:56 PreviewAutomationBroker.disconnect (x2)
609:49:57 PreviewAutomationBroker.connect / focusHost

Each time, server-browser was the only registered host. After each eviction the agent's lease and tab assignment were gone. The agent then opened a fresh tab with preview_open. When the desktop panel didn't attach it within DESKTOP_ATTACH_TIMEOUT, that tab ran headless in an isolated context (#16901). The user sees this as "the browser was signed in, then the agent says it isn't and loses the connection." It happens often enough that they have to step in during most browser tasks.

A related way the same session is lost: a nightly auto-update install (desktop.updates.install at 09:06:19) restarted the backend. The agent's next call failed with No server preview tab is open for this thread. Call preview_open first.

PR #16941 (keep the host on per-request timeouts) looks like it covers the main path here.

Posted by Claude Code (Claude Opus 5.5) via t3 triage, on behalf of the user.

Synced from GitHub

Scope correction — 15 October 2026: #16941 no longer fixes shared-host eviction. It only skips expired queued agent work (recordingStop exempt). It does not cancel running operations or fix Cloudflare verification. Host retention is proposed separately in #17871. Earlier #16941 scope/test claims below refer to the superseded broader revision; see the current PR description for the narrowed scope and verification.

Original update (historical scope)

@jamielmccormick Your trace matches the timeout/host-eviction path covered by #16941. I added an explicit navigation-timeout case in f07b86a: the host stays registered, both sessions keep their tab assignments, and the unrelated pending open can complete. All 58 broker tests pass, along with the server typecheck and targeted lint.

This is shared broker coverage; I have not run a native macOS desktop test. The backend-restart case is separate: this PR preserves registrations and tab assignments during per-request timeouts, but does not persist them across a backend restart.

Synced from GitHub

Still happens on macOS 26.7.1 arm64, Nightly 0.0.46-nightly.20261008.2833, which is newer than the .2819 report above. Times are UTC.

  • In one hour of server.trace (2026-10-09, 08:26–09:31), every broker timeout was followed by PreviewAutomationBroker.disconnect/closeConnection and a connect about 1 s later. That happened 23 times, after snapshot, evaluate, click, waitFor and navigate timeouts.
  • Provider logs from 6–8 Oct show 43 "No preview automation host is available" errors. 42 of them came within 20 s of a timeout in the same thread.
  • Codex threads hit it hardest because they send several preview calls at once. One timeout at 06:10:36 on 8 Oct took 7 parallel calls down with it.
  • After the reconnect, preview_status often returned available: false, tabId: null, and the agent had to open a new tab, which came up signed out.
Synced from GitHub

Still happening on macOS 26.6.2 arm64, Nightly 0.0.46-nightly.20261012.3010. Server trace, UTC, 2026-10-12, timeouts from my Claude Code thread:

109:22:15 evaluate timed out after 15000ms
209:25:12 snapshot timed out after 15000ms
309:25:28 PreviewAutomationBroker.disconnect x2, connect at 09:25:29
409:25:31 evaluate timed out, disconnect 09:25:47, connect 09:25:48
509:25:53 evaluate timed out, disconnect 09:26:09, connect 09:26:10

The first timeout came from a slow evaluate of mine. After that, plain snapshots and evaluates on that tab kept timing out, and every timeout evicted the host again. In the same window, a Facebook tab ended up on the headless page while my panel showed my signed-in page (#16901). I can't prove the eviction caused it, but it's the only odd event next to it in the traces.

Synced from GitHub

Scope correction — 15 October 2026: #16941 no longer fixes shared-host eviction. It only skips expired queued agent work (recordingStop exempt). It does not cancel running operations or fix Cloudflare verification. Host retention is proposed separately in #17871. Earlier #16941 scope/test claims below refer to the superseded broader revision; see the current PR description for the narrowed scope and verification.

Original update (historical scope)

Thanks for the 3010 trace: a slow evaluation should fail that request without taking the shared browser host down.

I rechecked main@7b6d9075 today. Its broker still disconnects the host after an unanswered foreground request. That is consistent with the reported failure pattern; the exact host involved still needs confirmation.

#16941 keeps the trusted server-browser host registered, revokes expired queued/active work, and bounds reads/capture. It retains the previously merged browser fixes, including #17693's separate reply grace.

Fresh local integration check of f4e1cc6d with that main: 303 tests in 17 files and server/contracts typechecks passed, conflict-free. The PR is still unmerged; official fork CI awaits authorization. These were Linux/Chromium checks, not a native macOS test of the patch. The #16901 profile/panel mismatch and Cloudflare verification remain separate.

If your trace records the disconnected host's clientId, could you share just that field? It would distinguish server-browser from a desktop host and help confirm whether this is the exact path.

Synced from GitHub

More Windows evidence from Codex-driven sessions, Oct 11 to 13 (nightlies before 0.0.46):

  • Preview automation snapshot timed out after 15000ms on LinkedIn profiles, followed on retry by HTTP request failed from the local T3 MCP server.
  • tool call failed for t3-code/preview_snapshot: Transport send error: Transport [codex_rmcp_client] ..., and the same transport error for preview_navigate.
  • Preview automation open timed out after 660000ms: one preview_open blocked for 11 minutes, then Preview automation navigate timed out after 15000ms on the next call.

Each time, the agent gave up on the T3 browser and finished in a different browser. Separately, on 0.0.46-nightly.20261015.3145, agent tabs in one thread moved from the desktop runtime to the server browser partway through a session, right after a few preview_click timeouts. That may be this eviction, filed separately as #19925.

Note

Grok responding on behalf of Julius.

From #19925 (Windows, nightly 0.0.46-nightly.20261015.3145): after preview_click timeouts, new agent tabs in the same session opened on the server browser (headless Chrome/154 UA) instead of the desktop, so signed-in sites looked signed out. This matches invoke evicting an unresponsive host (desktop included), pruning the session's lease, and failing over to the preferred server host. Neither preview_open nor preview_status reports a tab's runtime, so agents can't detect the switch.

Synced from GitHub

Additional macOS evidence on nightly 0.0.46-nightly.20261015.3145, the same build mentioned in the latest Windows report.

Environment: macOS 27.0 (26A428), Apple Silicon/arm64, T3 Code Desktop Nightly with its local server, Codex agents. The running server reports the same .3145 version. No patched build was used.

Reviewing retained provider histories from 13–15 October, we counted 23 distinct preview_snapshot calls returning structuredContent.error._tag = PreviewAutomationTimeoutError, across 9 agent histories (including one subagent). Calls were deduplicated by tool-call ID; missing-host errors were excluded. This is a historical count, not a controlled reproduction rate, and the earlier calls are not all attributed to the currently installed build.

One concrete sequence on 15 October, UTC, on the same tab:

text
115:33:45.122 preview_evaluate returns a 15000 ms timeout
215:34:01.131 broker starts waiting for snapshot (includeImage:false)
315:34:17.133 PreviewAutomationBroker.disconnect / closeConnection
415:34:17.178 snapshot returns PreviewAutomationTimeoutError (message: 15000 ms)
515:34:18.137 PreviewAutomationBroker.connect (~1 s after disconnect)
615:34:25.545 preview_status succeeds: available:true, loading:false
715:34:56.553 preview_navigate returns a 30000 ms timeout
815:35:14.087 broker starts waiting for another snapshot (includeImage:false)
915:35:30.088 disconnect / closeConnection again
1015:35:30.129 snapshot returns PreviewAutomationTimeoutError again
1115:35:31.090 connect again

In another history on 14 October, snapshots and DOM evaluations initially succeeded, then snapshots timed out and a subsequent small DOM evaluation failed too. Agents repeatedly had to finish browser verification in a different browser.

This corroborates that the timeout/disconnect/reconnect pattern is still occurring on macOS with .3145, including snapshots requested with includeImage:false. It does not establish which initial operation stalled, prove a desktop-to-headless transition, or demonstrate that another thread was cancelled by the same timeout. The trace spans we inspected did not expose the disconnected client's ID, so we cannot identify that host from these spans alone.

Posted with the user's authorization; investigation and wording assisted by Codex. Application URLs, project names, local paths and session identifiers have been omitted.

Synced from GitHub

Additional macOS evidence for host eviction after an automation timeout. This is from agent logs, not a live retest. Related: #16264 (closed) for the "Do not retry" wording, and #17871 for the open host-retention fix.

Environment. macOS 26.6.2 (Darwin 25.6), arm64, T3 Code Nightly desktop app open and connected to a local environment, Codex agents. Builds: 0.0.46 nightlies, 2026-10-07 to 10-09. Desktop traces show 0.0.46-nightly.20261008.2813 through 0.0.46-nightly.20261009.2873 for 10-08 onward. The 10-07 build was not recorded.

What the logs show (1,503 preview_* calls, 2026-09-19 to 10-19).

  • 15 calls failed with No preview automation host is available for <op> in environment <id>. … Do not retry. …. All 15 came within 1 s of a preview timeout on the same host, and each failed in 0 s.
  • In 12 of the 15, the agent's next preview call on the same host worked 8 to 38 s later. That gap is when the agent next tried, so it is an upper bound on recovery time, not a measurement.
  • A single timeout cascades inside a batch. At 2026-10-07 18:10:09Z, a preview_wait_for timed out. The navigate, wait_for, and evaluate calls that followed in the same second all failed with "no host". preview_status worked 17 s later.
  • After an eviction, a cached tab id no longer resolved. After the 18:10–18:11Z burst, the next calls at 18:34:34Z failed with:
    1Preview tab tab_1_<id> was not found for navigate. Omit tabId to use the current tab, or call preview_open.
    The same error came back for set_appearance, resize, and evaluate on the same tab. This looks like the "losing their current-tab assignments" part of #17871. That is an inference from timing.
  • No "no host" errors appear in these logs after 2026-10-09. I have not retested on 0.1.1-nightly.20261019.3373.

Example times (UTC) of "no host" errors: 2026-10-07 01:40:01, 06:24:35, 08:30:45, 08:32:35, 08:33:29, 17:28:45, 18:10:09 (x3), 18:11:01 (x4); 2026-10-08 02:41:41; 2026-10-09 00:22:38.

Why the wording matters. "Do not retry … use a headless browser" tells the agent to abandon the collaborative browser for a fault that clears in seconds. In our logs, agents sometimes switched tools after this message.

Suggestions, in case they are not already covered by #17871:

  1. Give "host evicted after a timeout / reconnecting" its own error tag, with a retry-after hint. Keep "Do not retry" for the case where no desktop or server host is registered at all.
  2. Keep tab ids valid across a host re-register, or return the replacement id in the error.