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
Opening a V2 TUI during an automatic update caused the shared managed service to be replaced, disconnected every existing TUI, cold-booted many location graphs concurrently, delayed SSE readiness, and left the new TUI slow and partially rendered. A later explicit service restart reproduced the reconnect herd and pushed location startup to 19 seconds.
This issue collects the coupled V2 managed-service lifecycle concerns exposed by the incident. Confirmed observations are separated from hypotheses; the current logs do not identify the dominant location-startup or memory owner.
Environment
opencode version during incident: 0.0.0-next-15293 updating to 0.0.0-next-15295
opencode version during follow-up capture: 0.0.0-next-15296
Keep several V2 TUIs connected to the managed background service from different directories.
Open another opencode2 TUI while a newer next version is available.
Allow the default automatic update policy to install the newer global CLI package.
Start a client from the newly installed version.
Explicit restart control
Keep seven V2 TUIs connected from several directories.
Run opencode2 service restart.
Observe reconnect attempts, service election, and location startup timings.
The automatic-update incident was observed once. The explicit restart reproduced the reconnect and cold-location herd.
Expected Behavior
Updating the globally installed CLI should not unexpectedly replace a shared service and interrupt all connected clients without coordinated UX.
A service replacement should expose one coherent updating/restarting state to connected TUIs.
Reconnecting clients should not create an unbounded cold-start herd across every recently active location.
Event-stream connection timing should distinguish a live-but-busy server from an unavailable server.
Startup and resource diagnostics should identify the expensive subsystem rather than only reporting one aggregate location duration.
Actual Behavior
A newly opened next-15293 TUI installed next-15295 in the background.
A subsequent next-15295 client required an exact-version service and replaced the healthy next-15293 service.
Six existing TUIs disconnected together during the automatic-update incident.
The replacement server cold-booted at least eight location graphs concurrently. The affected location took 11.97 seconds; other locations took up to 15.35 seconds.
The affected TUI's first SSE attempt timed out after two seconds, then connected on retry about 4.5 seconds later.
The reported session was created about 51 seconds after the original TUI launch and initially rendered as a partial home screen.
An explicit restart later disconnected seven TUIs. All seven reached reconnect attempt 4 and launched serve --service election attempts. One server won, then ten location graphs booted concurrently, taking up to 19.10 seconds.
CPU and memory remained high after startup. The available samples identify broad Bun/WebKit allocator and graphics regions but do not localize the retaining code path.
Additional Context
1. Automatic update and exact-version replacement
The default TUI forks an updater check before resolving the server:
The updater installs the global package in place. Both true and "notify" currently select the upgrade action, and the managed server also runs this updater every ten minutes:
15:46:26.110 TUI starts on next-15293
15:46:27.115 update check: current=15293 latest=15295
15:46:30.339 global Bun install updated to 15295
15:46:42.566 new TUI starts on 15295
15:46:42.943 six existing event streams disconnect
15:46:44.470 replacement serve --service starts
There is update-confirmation UI in the TUI for installation.update-available, but the CLI updater path above directly installs the package. Repository search found the event schema and consumer but no publisher in the V2 package set.
2. Cold-location herd
Automatic-update replacement timings:
/private/tmp 5,029 ms
/Users/kit 5,282 ms
/Users/kit/code/open-source 7,188 ms
.../opencode/packages/opencode-test-plugins 11,974 ms
/Users/kit/code/projects/Hex 12,372 ms
/Users/kit/code/open-source/effect-smol 12,829 ms
/Users/kit/code/open-source/openeval 15,329 ms
/Users/kit/code/open-source/browser-control 15,346 ms
Explicit restart at 16:09 UTC was a stronger control. Seven clients disconnected, all reached reconnect attempt 4, and seven serve --service contenders launched. Election produced one server (run=0349cbfd). Its ten concurrent location boots included:
/Users/kit 2,529 ms
/Users/kit/code/open-source 3,418 ms
/Users/kit/code/projects/Hex 11,006 ms
/Users/kit/code/open-source/browser-control 12,947 ms
/Users/kit/code/open-source/opencode 15,731 ms
.../opencode/packages/opencode 18,443 ms
.../opencode/packages/opencode-test-plugins 18,723 ms
/Users/kit/code/open-source/effect-smol 19,097 ms
location services booted is one aggregate timer around acquisition of the full location layer. It does not attribute time to configuration discovery, plugins, MCP, search/indexing, watchers, or scheduler contention.
3. Two-second SSE first-frame timeout
The TUI gives api.event.subscribe() two seconds to yield its first event, expected to be server.connected:
15:46:56.937 event stream connecting, attempt 0
15:46:58.938 disconnected: Timed out connecting to server
15:47:01.910 event stream connecting, attempt 1
15:47:03.470 event stream connected
The server was alive during this period and was concurrently completing location boots. The evidence shows first-frame latency under load; it does not yet show whether the delay occurred in HTTP acceptance, SSE setup, event-loop scheduling, or client processing.
4. Duplicate event log amplification
Each TUI logs durable events after decoding them from the shared SSE stream. During the incident:
Large resident regions in the server snapshot included approximately 1.3 GB WebKit Malloc, 382 MB MALLOC_SMALL, 373 MB MALLOC_LARGE, 359 MB IOAccelerator, and 240 MB JS VM Gigacage. The sampled TUI included approximately 1.2 GB WebKit Malloc, 437 MB JS VM Gigacage, 270 MB IOAccelerator, and 85 MB VM_ALLOCATE resident mappings.
vmmap warned that WebKit malloc-zone analysis was incomplete. The three-second stack samples were mostly unsymbolicated Bun/JSC frames and do not identify the retaining subsystem. No claim is made yet that event handling, OpenTUI, indexing, plugins, or another subsystem is the primary memory cause.
6. Observability gaps
No per-node location startup timings.
No explicit service lifecycle event for update pending, restart scheduled, draining, replacing, or ready.
No measurement separating TCP/HTTP connection, first SSE byte, and first decoded event.
No heap snapshot or allocation profile tied to server/TUI growth.
The shared text log reached 472 MB; rotation behavior was not visible in the incident evidence.
Open design questions
Which process owns update discovery and installation: each TUI, the managed service, or a separate launcher?
Should automatic update download/stage separately from activation?
What explicit user action or safe boundary permits replacement of a shared service with active clients and executions?
What state should connected TUIs render while an update is available, staged, restarting, reconnecting, or ready?
Should reconnecting clients lazily restore only their current location rather than eagerly recreating every recently active location graph?
Should SSE connection timeout measure transport establishment separately from first application event?
What is the intended text-log policy for dense durable events already stored in SQLite?
Which memory/CPU instrumentation can attribute retained resources to location services, session projections, event reducers, OpenTUI, plugins, or Bun/JSC?
Summary
Opening a V2 TUI during an automatic update caused the shared managed service to be replaced, disconnected every existing TUI, cold-booted many location graphs concurrently, delayed SSE readiness, and left the new TUI slow and partially rendered. A later explicit service restart reproduced the reconnect herd and pushed location startup to 19 seconds.
This issue collects the coupled V2 managed-service lifecycle concerns exposed by the incident. Confirmed observations are separated from hypotheses; the current logs do not identify the dominant location-startup or memory owner.
Environment
0.0.0-next-15293updating to0.0.0-next-152950.0.0-next-15296TERM=xterm-256color,COLORTERM=truecolor/bin/zshnext@warp-dot-dev/opencode-warp,~/.config/opencode/plugins/share-with-team.ts, and the repository debug workspace pluginReproduction
Automatic-update incident
opencode2TUI while a newernextversion is available.Explicit restart control
opencode2 service restart.The automatic-update incident was observed once. The explicit restart reproduced the reconnect and cold-location herd.
Expected Behavior
Actual Behavior
next-15293TUI installednext-15295in the background.next-15295client required an exact-version service and replaced the healthynext-15293service.serve --serviceelection attempts. One server won, then ten location graphs booted concurrently, taking up to 19.10 seconds.Additional Context
1. Automatic update and exact-version replacement
The default TUI forks an updater check before resolving the server:
packages/cli/src/commands/handlers/default.tsThe updater installs the global package in place. Both
trueand"notify"currently select theupgradeaction, and the managed server also runs this updater every ten minutes:packages/cli/src/services/updater.tspackages/cli/src/server-process.tsManaged server resolution defaults to exact-version replacement.
Service.start()kills a healthy mismatched service before spawning the replacement:packages/cli/src/services/server.tspackages/client/src/effect/service.tsIncident timeline, UTC:
There is update-confirmation UI in the TUI for
installation.update-available, but the CLI updater path above directly installs the package. Repository search found the event schema and consumer but no publisher in the V2 package set.2. Cold-location herd
Automatic-update replacement timings:
Explicit restart at 16:09 UTC was a stronger control. Seven clients disconnected, all reached reconnect attempt 4, and seven
serve --servicecontenders launched. Election produced one server (run=0349cbfd). Its ten concurrent location boots included:location services bootedis one aggregate timer around acquisition of the full location layer. It does not attribute time to configuration discovery, plugins, MCP, search/indexing, watchers, or scheduler contention.3. Two-second SSE first-frame timeout
The TUI gives
api.event.subscribe()two seconds to yield its first event, expected to beserver.connected:packages/tui/src/context/sdk.tsxpackages/tui/src/context/sdk.tsxAffected TUI timeline:
The server was alive during this period and was concurrently completing location boots. The evidence shows first-frame latency under load; it does not yet show whether the delay occurred in HTTP acceptance, SSE setup, event-loop scheduling, or client processing.
4. Duplicate event log amplification
Each TUI logs durable events after decoding them from the shared SSE stream. During the incident:
Identical aggregate IDs and sequence numbers appeared under seven client run IDs. See #36283 for the narrow logging-semantics issue.
5. CPU and memory evidence
At 12:44 local time,
psreported:RSS includes resident shared mappings and should not be summed as unique physical memory.
vmmap -summaryprovided a more conservative measurement:Large resident regions in the server snapshot included approximately 1.3 GB
WebKit Malloc, 382 MBMALLOC_SMALL, 373 MBMALLOC_LARGE, 359 MBIOAccelerator, and 240 MBJS VM Gigacage. The sampled TUI included approximately 1.2 GBWebKit Malloc, 437 MBJS VM Gigacage, 270 MBIOAccelerator, and 85 MBVM_ALLOCATEresident mappings.vmmapwarned that WebKit malloc-zone analysis was incomplete. The three-second stack samples were mostly unsymbolicated Bun/JSC frames and do not identify the retaining subsystem. No claim is made yet that event handling, OpenTUI, indexing, plugins, or another subsystem is the primary memory cause.6. Observability gaps
Open design questions