Skip to content

Desktop 2.0.15 (Windows): renderer unresponsive on every launch (main thread pinned creating per-project stores) #51028

Closed

Description

@makerwitawat

Description

On Windows x64, desktop 2.0.15 freezes a few seconds after the window appears, on every
launch. Electron logs renderer unresponsive and the sampled stacks are entirely inside the
renderer's own JavaScript: the app builds one persisted reactive store per project
synchronously on the main thread. The window never recovers (user had to kill it each time).

The main process and the bundled v2 CLI are healthy: main.log shows
v2 CLI background service ready in ~1–2 s, no server errors, and the v2 CLI background
service stays up. Relaunching does not help. On the same machine, 2.0.6 showed the same
symptom class 6/6 launches (samples land in different chunks, same work), so this is not a
one-off.

OpenCode version

Desktop 2.0.15 (Windows x64, packaged). For reference, the 2.0.6 export from the same machine
reports Electron 42.10.1 / Chromium 148.0.7778.280 / Node 24.18.1.
Bundled CLI: 2.0.15. Renderer: oc://renderer/index.html → assets/main-C5b0PwS_.js.

Steps to reproduce

  1. Install/launch desktop 2.0.15 on Windows with an existing workspace history
    (this machine: 51 projects, 71 session directories, 1,278 sessions).
  2. Leave the app alone for 10–60 s.
  3. Window stops redrawing; window.log gets renderer unresponsive plus sampled stacks;
    the app does not recover.

Expected behavior

Window stays responsive; per-project stores are created lazily or off the main thread.

Actual behavior

Renderer main thread saturates while creating stores for every project; UI frozen.

Evidence

window.log (run 20260924T034628, launched 10:46:28, unresponsive 10:46:59, 6 samples):

[error] (window) renderer unresponsive {
  window: '03c23a24-a395-432a-856c-051f0830558f',
  currentURL: 'oc://renderer/index.html'
}

at Object.getPrototypeOf (<anonymous>)
at da (oc://renderer/assets/main-C5b0PwS_.js:2:66760)          <- SolidJS wrap(): reactive Proxy
at Ta (oc://renderer/assets/main-C5b0PwS_.js:2:70097)          <- SolidJS createStore()
at oc://renderer/assets/main-C5b0PwS_.js:685:84935             <- g = Ta({ project, projectMeta, icon, ... }) in createChildStore()
...
at Object.C [as child] (oc://renderer/assets/main-C5b0PwS_.js:685:86639)
at d (oc://renderer/assets/main-C5b0PwS_.js:685:111932)        <- resolve(project)
at Proxy.map (<anonymous>)
at Object.fn (oc://renderer/assets/main-C5b0PwS_.js:685:112197) <- memo: f = () => n.list().map(d)

Same run, other samples:

at String.replaceAll (<anonymous>)
at sE (..main-C5b0PwS_.js:21:49375)                            <- directory normalization
at g (..:685:83350) / Array.filter / y (..:685:83951) / f      <- store-manager LRU pass per created store
at b (..:685:84805)                                            <- createChildStore(directory)
at Object.C [as child] ... at d ... at Object.fn (projects memo)

at Object.create (<anonymous>)
at dS (..:21:22888) / mS (..:21:23018) / HS (..:21:26226)      <- effect Schema encoding chain
at Object.$E [as persist] (..:21:56617 / 21:56643)             <- effect persist(): vcs / project / icon
at ..:685:84609 / 685:84165                                    <- inside createChildStore()

2.0.6 run (20260924T034326), same job in the older bundles:

at WeakMap.get / Object.getPrototypeOf
at Sg (language-D4DVEHmN.js:15:26133)                          <- SolidJS wrap() recursion
at e_ / U_ / G_ / Object.gS [as persist] (language-…:15:70413)
at wx + String.replaceAll (language-…:15:63149)
at Array.sort (runtime-…:639:50064) / Array.filter (runtime-…:639:51311)

The 2.0.6 main.log also shows imported legacy store files { imported: 27, files: [….dat…] }
right before the freeze (v1 → v2 store migration). The migrated store itself is small
(drafts.sqlite: 783 documents, largest 15 kB; largest blob 495 kB), so payload size is not
the issue.

Full logs, all samples and the annotated symbol legend (offsets resolved against
app.asar), user name redacted: https://gist.github.com/makerwitawat/c8a8efc0218d502a90c166dceee56f08

Root-cause hypothesis (from the extracted bundle, not a debugger session)

  • main-C5b0PwS_.js:685:* is the workspace store manager. child(directory) →
    createChildStore (685:84805) creates per directory: 3 ×
    persist(serverWorkspace(scope, dir, "vcs" | "project" | "icon")) (each deriving an
    effect Schema encoding chain, visible above) plus another
    createStore({ project, projectMeta, icon, config, get path(), get provider(), get agent(), get command(), get reference(), get mcp(), get lsp(), get vcs(), … }).
  • Each creation also runs LRU bookkeeping (f/m/h/g/y) that walks Object.keys(allStores)
    and normalizes every entry (sE) — O(n) per created store, i.e. O(n²) over the project list.
  • The trigger is the projects memo let f = E(() => n.list().map(d)) (685:112197) with
    d calling l.child(worktree) (685:111932): every project is materialized synchronously
    on the renderer thread, and the memo is re-evaluated as persisted vcs/projectMeta/icon
    stores become ready.

Operating System

Windows (win32 x64), Electron 42.x build. Terminal: n/a (desktop app; the same machine's CLI
runs fine against the same DB).

Related issues

Activity

  1. userbox020 commented on Sep 26, 2026

    @userbox020

    Confirmed on Windows x64 with Desktop 2.0.17. This appears to be the same failure and stack described above.

    Additional reproduction details:

    • The first 2.0.17 launch imported 791 legacy desktop store files.
    • Every subsequent launch became unresponsive in roughly 18-20 seconds.
    • Samples repeatedly landed in persist, serverWorkspace, SolidJS proxy/store operations, and Proxy.map while materializing workspace stores.
    • One run eventually ended with reason: 'oom' / exit code -536870904; the renderer had grown to approximately 4 GB.
    • The bundled background service was healthy and the standalone CLI continued working.
    • Uninstalling and reinstalling Desktop did not help. %APPDATA%\ai.opencode.desktop was preserved, and the old staged 2.0.17 opencode-cli.exe background service survived/reconnected (probed: true).

    Verified recovery/workaround:

    1. Exit Desktop and stop only its OpenCode.exe processes and the staged %APPDATA%\ai.opencode.desktop\cli\2.0.17\opencode-cli.exe process.
    2. Rename %APPDATA%\ai.opencode.desktop to a backup name instead of deleting it.
    3. Install Desktop 2.0.18.
    4. Launch Desktop, allowing it to create a fresh profile and stage a fresh 2.0.18 background service.

    Result:

    • No renderer unresponsive, OOM, or renderer-process-gone events during a monitoring period longer than the previous deterministic crash window.
    • Renderer memory stabilized around 194-232 MB instead of increasing beyond 4 GB.
    • All Electron processes remained responsive.
    • The existing shared OpenCode database and standalone CLI were left untouched. In this case the database was unusually large (42.65 GB plus a 2.48 GB WAL, with 4,562 sessions), but Desktop worked after resetting only the desktop profile, so database size alone was not the immediate trigger.
    • A few temporary server thrashing detected warnings appeared during first-launch initialization, then stopped without freezing the UI.

    This is a confirmed workaround, not proof that 2.0.18 fixes the underlying eager/O(n^2) store-materialization behavior. The important recovery step was starting with a fresh desktop profile; a normal uninstall/reinstall did not remove the problematic persisted state.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions