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
On Windows, the browse daemon's terminal-agent watchdog gets stuck in a permanent respawn loop: it spawns a fresh bun run terminal-agent.ts every 60s (AGENT_WATCHDOG_TICK_MS) even though the previous agent is alive and its pid record is fresh. Each spawn flashes a visible bun.exe console window (polyfill drops windowsHide — fix in PR #2294), old agents are never reaped, and the respawn circuit-breaker can mathematically never trip.
13:19:43.206 START bun run ...\terminal-agent.ts (parent 35744)
13:20:43.368 START bun run ...\terminal-agent.ts (parent 35744)
13:21:43.500 START bun run ...\terminal-agent.ts (parent 35744)
A second daemon (pid 47248, different project state dir) interleaved its own 60s loop → a console flash every ~30s wall-clock.
Leak — 7 spawns vs 1 exit in a 6-minute capture; process count 3 → 9 in ~10 minutes, ~90 MB working set. One daemon had been orphaned (its parent process dead) and looping like this for 2 days. The daemon-side kill path (spawnTerminalAgent kills the pid in the record before spawning) doesn't cover them: 9 agents alive with only 2 pid records in existence.
The respawn happens despite a healthy agent. At the time of the respawns, the terminal-agent-pid records existed, were freshly written (seconds-old), and pointed at running pids.
isProcessAlive is exonerated. I ran the exact implementation under node --require bun-polyfill.cjs (the daemon's real runtime): it returned true for a live agent pid and false for a dead one, with clean tasklist CSV output. So the mis-detection is somewhere else — possibly a stateDir/projectDir mismatch between where the daemon looks and where the agent writes (I did not isolate it; occasionally a tick is skipped, so the check does sometimes pass).
The circuit-breaker is dead code.RESPAWN_GUARD_MAX = 3 within RESPAWN_GUARD_WINDOW_MS = 60_000, but the watchdog tick is also 60s — entries older than the window are pruned before counting, so respawnHistory can hold at most ~1 entry at each tick and the guard can never reach 3. The "manual restart required" log line is unreachable at default settings.
Find why the watchdog considers a live, freshly-recorded agent dead (stateDir resolution seems the prime suspect).
Make the guard window meaningfully larger than the tick (e.g. 10 min window / tick 60s), so a genuine crash-loop actually trips it.
Reap: kill the previous agent by pid before spawning even when the record lookup misses, or track children directly — observed agents do self-exit when their daemon dies, but not when superseded.
Consider a daemon-side "am I orphaned?" check — the 2-day looper's parent was long dead.
Happy to provide the raw watcher logs or test a branch on this machine.
Summary
On Windows, the browse daemon's terminal-agent watchdog gets stuck in a permanent respawn loop: it spawns a fresh
bun run terminal-agent.tsevery 60s (AGENT_WATCHDOG_TICK_MS) even though the previous agent is alive and its pid record is fresh. Each spawn flashes a visiblebun.execonsole window (polyfill dropswindowsHide— fix in PR #2294), old agents are never reaped, and the respawn circuit-breaker can mathematically never trip.Environment
a3259400(update-check reportsUP_TO_DATE 1.60.1.0)node.exe dist/server-node.mjswithbun-polyfill.cjs(the documented Windows fallback)Measured behavior
Respawn cadence — process-creation watcher, one daemon (pid 35744), exact 60s beat:
A second daemon (pid 47248, different project state dir) interleaved its own 60s loop → a console flash every ~30s wall-clock.
Leak — 7 spawns vs 1 exit in a 6-minute capture; process count 3 → 9 in ~10 minutes, ~90 MB working set. One daemon had been orphaned (its parent process dead) and looping like this for 2 days. The daemon-side kill path (
spawnTerminalAgentkills the pid in the record before spawning) doesn't cover them: 9 agents alive with only 2 pid records in existence.The respawn happens despite a healthy agent. At the time of the respawns, the
terminal-agent-pidrecords existed, were freshly written (seconds-old), and pointed at running pids.isProcessAliveis exonerated. I ran the exact implementation undernode --require bun-polyfill.cjs(the daemon's real runtime): it returnedtruefor a live agent pid andfalsefor a dead one, with cleantasklistCSV output. So the mis-detection is somewhere else — possibly a stateDir/projectDir mismatch between where the daemon looks and where the agent writes (I did not isolate it; occasionally a tick is skipped, so the check does sometimes pass).The circuit-breaker is dead code.
RESPAWN_GUARD_MAX = 3withinRESPAWN_GUARD_WINDOW_MS = 60_000, but the watchdog tick is also 60s — entries older than the window are pruned before counting, sorespawnHistorycan hold at most ~1 entry at each tick and the guard can never reach 3. The "manual restart required" log line is unreachable at default settings.Suggested directions
windowsHidein the polyfill) — stops the visible flashing; no-op off Windows.Happy to provide the raw watcher logs or test a branch on this machine.
🤖 Generated with Claude Code