Repository navigation
Description
What happened
Desktop, up to date with the current release (v2.2.0), session on the built-in server. The browser had been in use in the session: a page stopped loading, and afterwards the side panel's new-tab view showed only Review / Terminal / Open file. The Browser launcher was gone and did not come back. Quitting and reopening the app restored it.
Why it can't recover
The launcher (MenuItem in packages/gui-plugins/src/browser/renderer.tsx) shows only when model.available(view) && model.attached(view). The browser model in this window has terminal states that stay in place until the renderer reloads, and each of them hides the launcher:
- Server flagged
unsupported. Inpane.ts, if the attach stream fails withrpc.unavailable/rpc.method_not_found/rpc.invalid_inputbefore the firstattachedcontrol message, the reason becomesbrowser.pane.unsupported.model.tsthen setsstate.unsupported[server.id] = true, andconnection.tssetsblocked = true. After that,available()is false for every session on that server in the window, so both the launcher and thebrowser.opencommand (⌃⌘B) are disabled. On the built-in server,rpc.unavailablecan be transient:core/src/rpc.tsreturns it while a location's registration is missing or was closed by routing-cache invalidation. A reconnect that lands in that window permanently marks a server that supports the browser as unsupported. browser.pane.replaced. When another attachment takes over the session (another desktop window, or any attach that wins the race),connection.tssetsblocked = trueandstate.browser = null, soattached()becomes false and the launcher disappears. Nothing in this window ever registers again.- Suspended before the first inventory.
suspend()keepsstate.browser. If that is stillnullwhen the pane suspends,attached()is false and the launcher disappears, even though opening it is exactly what would wake the pane. Only session activity or ⌃⌘B can bring it back.
We don't know which of these paths this report hit (it was cleared by relaunching before we could check ⌃⌘B's error text). Paths 1 and 2 both leave the window stuck until the app restarts.
Expected
- A transient
rpc.unavailablefrom the built-in server (or any server that has the browser plugin) should not mark the server unsupported. Reserveunsupportedfor a definitive missing RPC/method, or retry with backoff and re-probe on reconnect or location change. - A
replacedwindow should be able to take control back, at least when the user explicitly opens the browser, instead of being blocked for the rest of the window's life. - The new-tab launcher should not depend on
attached(). It is itself a way to wake or reconnect the pane, so show it wheneveravailable()is true and let opening it register.
Environment
- OpenCode Desktop v2.2.0 (macOS), built-in server
- Observed 2026-10-28 ~20:50 UTC
Activity
evachxji commentedon Oct 29, 2026
I reproduced the detached-pane launcher case and have a focused fix with regression coverage. I'll open a PR targeting dev.