UPDATE (Aug 19): Root cause found — see reply below.
browser_cdpwith{"method":"Page.reload"}reloads the Cursor workbench window, not the browser view. Six calls, six teardowns, matched to the second. Please disregard the feature-flag hypothesis in this post.
Where does the bug appear (feature/product)?
Cursor IDE
Describe the Bug
Cursor repeatedly tears down all extension hosts and re-initializes the workbench with no user action, killing in-flight agent turns. Five times in four hours. FOUR OF THE FIVE EVENTS HAVE NO LOGGED REASON ANYWHERE IN CURSOR’S LOGS.
It is NOT a crash — verified:
- The renderer OS process is never replaced (same pid, alive 4+ hours across all five events), so this is a workbench reload, not a renderer crash.
- The app process is never replaced.
- All extension hosts exit code 0 — a deliberate, graceful shutdown.
- No macOS crash report for any event (~/Library/Logs/DiagnosticReports).
- No jetsam / memorystatus kill in the unified system log across the window.
Signature, identical all five times:
exthost.log: “Extension host terminating: renderer closed the MessagePort”
main.log: “Extension host with pid exited with code: 0, signal: unknown” (x4 hosts)
main.log: “[PowerMainService] Releasing N orphaned wakelock(s) … releaseReason=ipc-client-disconnect”
then full workbench re-init:
renderer.log: “[CursorExtensionIsolationService] Extension isolation is enabled”
renderer.log: “Placing extension(s) … on a separate extension host”
Everything I searched for that would explain it — ZERO hits, all of them:
“terminated unexpectedly” — 0
“Automatically restarting the extension host” — 0
“Extension host was not stopped because of veto” — 0
“[MemoryMonitor]” — 0
“[RendererPing] window … blocked” — 0
“Extension host watchdog reported” — 0
“is unresponsive” — 0
Also ruled out: multi-root first-folder change (this is a single-folder window), workspace trust change, profile switch, extension install/update, MCP config change.
THE CONTRAST THAT SHOWS THIS IS A LOGGING GAP, NOT A MYSTERY:
A sixth event the same afternoon — the idle extension-host killer — logged its reason completely:
[IdleTimeContribution] Hard stopping cursor builtin extension hosts after 30 idle minutes (threshold=30, freeMemory=3.1%, freeMemoryThreshold=10%).
Hard stopping local extension hosts (Idle extension host killer) [cursor builtin hosts only].
That event also behaved correctly: builtin hosts only, user host left alive, NO workbench re-init, hosts restarted on refocus.
So Cursor CAN log this class of action, and does — on one path. The other four events took a path that emits nothing on success. That gap is the bug I am reporting.
Steps to Reproduce
I cannot trigger it on demand — it arrives unattended. It reproduced five times in four hours under this workload, and also in the prior session that morning, so it is not rare on this setup.
Conditions present every time:
- Open a single-folder window (not a .code-workspace) on a large JavaScript monorepo with sibling git worktrees.
- Run several agent conversations concurrently, with MCP servers connected and Cursor hooks configured.
- Leave long agent turns generating (multi-minute turns are the ones that get killed).
- Wait. Within roughly 10–90 minutes, all extension hosts exit code 0 and the workbench re-initializes, cutting off whatever was generating.
Event times observed (local):
session 20260818T085806 — 09:33:39
session 20260818T133849 — 15:28:22, 16:53:41, 17:02:58, 17:22:57
(plus 15:59:40, which WAS the idle killer and logged its reason — include as the control case)
Gaps between events shortened over the session: 85 min, then 9 min, then 19 min.
TIMING FINGERPRINT — this may be the fastest route to reproducing it internally. Cursor polls feature gates every 5 minutes (“Mirrored gate (reason=gate-change, …)”), and two events sit right on that boundary:
gate-change 15:28:04 → event 15:28:22 (18 seconds later)
gate-change 17:18:10, next poll due 17:23:10 → event 17:22:57 (13 seconds before)
If a server-pushed flag rollout is rearranging extension hosts on live clients, flipping the relevant gate against a client with an agent mid-generation should reproduce it immediately.
How to confirm from my side: check the logs for the absence of every marker listed in the description while the MessagePort-close + code-0 exits are present.
Expected Behavior
Four things, in order of how cheap they are for you:
-
LOG THE CALLER on the graceful extension-host stop path — command id, contribution name, or flag id — exactly as the idle killer already does. This is a one-line change and the single highest-value fix here. Right now the success path of that stop emits nothing, so this is undiagnosable by users and unsupportable by your team.
-
DO NOT RESTART EXTENSION HOSTS WHILE AGENT GENERATIONS ARE IN PROGRESS. The idle killer already performs exactly this check (it skips when there is in-progress AI work or a background-task wait). Whatever path this is should honor the same guard, or defer until idle.
-
GATE REMOTE-CONFIG-DRIVEN HOST REARRANGEMENT BEHIND IDLE, if a server-pushed flag refresh is the trigger. Rolling out a flag should never interrupt a running agent on a live client.
-
SURFACE IT IN THE UI when hosts must be restarted, so it does not read to the user as a crash.
Expected user-visible behavior: either the restart does not happen while I have agents running, or — if it must — I am told it happened and why, and I can find the reason in the logs afterward.
Operating System
MacOS
Version Information
Cursor 3.16.17
Electron 40.10.3 | Chromium 144.0.7559.236 | Node 24.15.0
macOS 26.6.1 (build 25G76) | Mac15,6 — Apple M3 Pro | 18 GB RAM
For AI issues: add Request ID with privacy disabled
69e7aea3-2eb5-4831-870a-c34bb0094337
Additional Information
IMPACT
- In-flight agent work is destroyed. Wakelocks release as ipc-client-disconnect mid-generation. The longest-running agent turns are hit hardest, because they are the most likely to be running when the restart lands.
- Unattributable. With no logged reason this is indistinguishable from a crash. I spent hours ruling out RAM, browsers, git worktrees and the TypeScript server before proving Cursor did it deliberately.
- Escalating within a session: gaps of 85 min, then 9 min, then 19 min.
- Unsupportable. Anyone who reports “Cursor keeps restarting” for this cause cannot be helped, because the product recorded nothing.
LEADING HYPOTHESIS
The graceful stopExtensionHosts success path emits no log line. The only unattended trigger consistent with this window’s configuration is an extension-enablement / host-placement change (updateRunningExtensions) — which is precisely what the log shows Cursor doing immediately after every event (“Extension isolation is enabled”, “Placing extension(s) … on a separate extension host”). Combined with the 5-minute gate-poll timing above, a server-pushed feature-flag refresh is the most likely trigger.
SECONDARY BUG (related, separate): diagnostics ignore jsconfig.json exclusions and OOM the semantic TypeScript server.
ReadLints / VscodeDiagnosticsExecutor forces files into the SEMANTIC TypeScript server even when those files are excluded by the project’s jsconfig.json.
On a JavaScript monolith with sibling git worktrees, a single agent lint call on an excluded path pulled roughly 19,000 additional files into the semantic server and drove it into its maxTsServerMemory cap:
crashing thread: tsserver[6.0.3]: semantic
node::OOMErrorHandler(char const*, v8::OOMDetails const&)
v8::internal::V8::FatalProcessOutOfMemory(…)
Reproduced twice in one afternoon, same sequence each time:
lint request on excluded worktree paths
→ ~6s later “Couldn’t wait on latest linter errors: Timeout has occurred”
→ tsserver SIGABRT (OOM), macOS .ips crash report written
Expected: a diagnostics request for a path excluded by jsconfig.json should not load that file’s entire transitive project into the semantic server. Honor the exclusion, or fail fast.
Current workaround: typescript.tsserver.useSyntaxServer: “always”, which disables semantic language features entirely. That is not an acceptable long-term answer for a JavaScript codebase.
EVIDENCE AVAILABLE ON REQUEST (happy to send privately)
- Both full Cursor log sessions covering all events
- The two macOS .ips crash reports for the tsserver OOM aborts
- A 20-second-interval process sampler covering the window, confirming the renderer pid never changes
Does this stop you from using Cursor
Sometimes - I can sometimes use Cursor