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
{{ message }}
Repository navigation
App frequently becomes unresponsive when opening a session in Desktop V2 #51423
From my observation, the trigger seems completely random: the same session can sometimes open normally, but other times it immediately freezes upon opening; sometimes the issue doesn't occur even after prolonged use, while other times it freezes right when opening the very first session.
When it becomes unresponsive, nothing is clickable except for the buttons in the title bar. After a while, a "Not Responding" dialog pops up.
Plugins
None
OpenCode version
All versions since I upgraded to V2, including the latest 2.0.18
Steps to reproduce
Upgrade from Desktop V1 to V2
Open OpenCode and wait for the data migration to complete
This issue might be a duplicate of existing issues. Please check:\n- #51028: Windows Desktop V2 renderer becomes unresponsive around startup, with V1-to-V2 store migration also noted.\n- #36379: Desktop renderer hangs when opening sessions with very large message histories.
Analysis of the attached debug bundle (opencode-debug-20260926T001640.zip)
I went through the logs from the debug export and sharing the findings in case they help triage.
The freeze is renderer-side, not backend/service-side
main.log is clean in every session: startup, v2 CLI/service startup, and the V1→V2 data migration all complete normally.
server-1/opencode.log (~62k lines) shows nothing at the freeze timestamps; its only ERROR entries are from June and unrelated (aborted runs).
Every freeze is recorded in window.log as renderer unresponsive for the main window.
The unresponsive events fire exactly when a session is opened
In 5 of the 14 captured sessions, window.log logged renderer unresponsive — each one ~20 s after app start, i.e. right when the first session was opened (times below are local):
Session dir
app starting (main.log)
first renderer unresponsive (window.log)
20260925T235418
07:54:18
07:54:39
20260926T001134
08:11:34
08:11:54
20260926T001612
08:16:13
08:16:40
Sampled stacks all land in the message list's stick-to-bottom virtualizer path
The renderer unresponsive samples captured by the main process always point at the same code path — a virtualized list (looks like TanStack Virtual) performing scrollToEnd on mount/measurement:
at Array.Re (oc://renderer/assets/main-C8RBRwI4.js:2:12238)
at Object.active (oc://renderer/assets/route-CHhjG5_X.js:89:64925)
at n (oc://renderer/assets/route-CHhjG5_X.js:89:51650)
at Object.scrollToFn (oc://renderer/assets/route-CHhjG5_X.js:89:53808)
at Ba._scrollToOffset (oc://renderer/assets/route-CHhjG5_X.js:2:44160)
at Ba.scrollToIndex (oc://renderer/assets/route-CHhjG5_X.js:2:42710)
at Ba.scrollToEnd (oc://renderer/assets/route-CHhjG5_X.js:2:43143)
Other samples enter the same class from different entry points: Ba.scheduleScrollReconcile, Ba.getOffsetForIndex, P.resizeItem. Bundle hashes differ between builds (route-CDROkuzn.js, route-D7t6Qi_B.js, route-CHhjG5_X.js) but the offsets are identical, so it is the same code across 2.0.x.
renderer.log shows a ResizeObserver storm
Sessions that froze show bursts of ResizeObserver loop completed with undelivered notifications, up to 248 lines in a single session:
20260925T235000: 248
20260925T235534: 205
20260925T152241: 74
One possibly relevant detail: renderer.log starts with Slow network is detected. … Fallback font will be used while loading: oc://renderer/assets/Inter.ttf. If the webfont swaps in after the list has already measured and scrolled, item heights change post-measurement — exactly the kind of event that would kick off a measure → scroll → measure loop.
How this explains the reported symptoms
Freeze on session open: the list mounts and sticks to the bottom; item heights change (late font swap, code blocks/diffs/images) → ResizeObserver re-measures → scrolls again → the loop pegs the renderer main thread at 100%.
Randomness: whether the loop converges depends on font-load timing, item height variance, and window size — so the same session sometimes opens fine.
Title bar stays clickable: the native caption buttons are handled by the OS, not by the frozen renderer.
Relation to existing issues
This looks like the same family as #33712, #34289, #34038, #37997, #38296, #43355, #48633. One difference that may be useful for triage: in my captures the sampled stacks sit in the session message list virtualizer (scrollToEnd stick-to-bottom), not in the composer-region observers analyzed in #33712. Also note PR #44883 only suppresses the ResizeObserver log noise — the freeze itself still reproduces on 2.0.18.
Additional reproduction on Windows 11 with desktop 2.0.32 (latest per the updater; fresh NSIS install).
Environment
opencode desktop 2.0.32, Windows 11 Home (build 26200), x64, Intel i5-1335U, 15.7 GB RAM
No third-party plugins that affect rendering
Local DB integrity checked (PRAGMA quick_check = ok) — this is not a corrupt-store problem
Symptom
The renderer becomes unresponsive 17–18 seconds after launch, while the first session's message list is rendering. The main-process watchdog logs renderer unresponsive and then collects stack samples; the UI stays wedged and has to be force-killed.
Occurrences on 2026-10-19 (local time, UTC+5:30), each on a fresh launch:
08:10:09 (launched 08:09:51)
08:12:02 (launched 08:11:44)
21:54:29 (launched 21:54:12)
21:56:57 (launched 21:56:39)
Two consecutive launches froze exactly 17 s and 18 s after process start. A later launch restored the same session without freezing, so this is timing-dependent, not purely data-dependent. The session opened was moderate in size (~550 messages, ~1,600 parts).
at Ag.M.resizeItem (oc://renderer/assets/route-BYzALZ62.js:9:54530)
at Ag.M.resizeItem (oc://renderer/assets/route-BYzALZ62.js:9:57988)
at Map.forEach (<anonymous>)
at Ag.M.resizeItem (oc://renderer/assets/route-BYzALZ62.js:9:57959)
at Object.me (oc://renderer/assets/main-CZyBNj5O.js:2:5071)
at Map.delete (<anonymous>)
at Ag.M.resizeItem (oc://renderer/assets/route-BYzALZ62.js:9:54640)
Same measure/resize ↔ scroll-to-end loop in the message-list virtualizer described above (resizeItem, _scrollToOffset, scrollToIndex).
renderer.log also contains repeated:
ResizeObserver loop completed with undelivered notifications
and at startup (before the first session renders):
Slow network is detected. ... Fallback font will be used while loading: oc://renderer/assets/Inter.ttf
which is consistent with the late-webfont-swap theory (items re-measured after the first layout pass).
Notes
Force-kill + relaunch reproduces it reliably; the freeze always lands ~20 s after start, never later in the session.
Happy to attach the full debug bundle (opencode-debug-20261019T162611.zip, ~500 KB) if useful.
Root cause found + a working local fix (2.0.32, Windows)
Following up on the earlier evidence dump: the hang is not GPU, not the session data, and not the DB. It is a chat virtualizer microtask busy-loop in the renderer.
What the watchdog samples show
The Electron "renderer unresponsive" stacks always land in the same two places (bundled renderer asset route-BYzALZ62.js):
at Array.eee (main-CZyBNj5O.js:2:12239)
at Object.active (route-BYzALZ62.js:10:9061)
at n (route-BYzALZ62.js:9:51932)
at Ag.M.resizeItem (route-BYzALZ62.js:9:54542) <- overridden resizeItem
at route-BYzALZ62.js:9:57988
at Map.forEach (<anonymous>)
at route-BYzALZ62.js:9:57959 <- measure-all loop (je)
at ke (route-BYzALZ62.js:9:57631) <- tail auto-scroll
at route-BYzALZ62.js:9:58058
at le (route-BYzALZ62.js:9:53365) <- observeElementOffset callback
at ke (route-BYzALZ62.js:9:57663)
at route-BYzALZ62.js:9:58058
The loop
je() (the tail/measure pass) queues a queueMicrotask that measures every mounted chat row through the overridden M.resizeItem, and the resize-apply microtask ends by calling ke() (tail auto-scroll) and then je() again. Each iteration mounts/measures/scrolled content that queues another microtask. Because the chain never yields to the event loop, timers never run — including whatever marks markdown blocks data-markdown-ready. The tail mode only exits when everything is measured and no markdown block is pending (ce.querySelector('[data-component="markdown"]:not([data-markdown-ready])')), so the pane stays visibility: hidden (the blank window) while memory climbs to 1–3 GB.
Throttling MutationObserver/ResizeObserver from the outside does not help — the loop is driven by microtasks, not observer delivery.
Local fix (one line in the renderer bundle)
Debounce the measure microtask so the cycle can never run tighter than 150 ms and always yields to the event loop:
Result on the same machine and app build: an 800k-token session (529 messages, the same class of session that froze before) renders, scrolls and stays responsive; renderer idles around 70 MB heap / ~0% CPU, and the chat pane becomes visible in about a second. Cold starts no longer hang.
Happily re-testing any official fix — but the underlying issue looks like the tail-mode completion condition (markdown-ready + measurement settling) can be starved by the measurement microtask chain itself, so a yield/debounce in that path (or dropping visibility:hidden while waiting) would be the place to patch upstream.
Thanks for the detailed report and the log analysis, and thanks to @natsforai-lab for the extra reproduction on 2.0.32.
I couldn't try to reproduce this here: it needs the desktop app on Windows, and the sandbox I run in is headless Linux, so a maintainer with that setup will need to confirm it.
The code path in your stack samples is still on the current dev branch, in the session timeline's 'scroll to the bottom on open' handling. That fits the measure → scroll → measure loop you and @natsforai-lab described. Your timings, stack samples and the note that the debounce workaround stops the hang should help whoever looks at it.
Related issues (none of them looks like the same cause):
Fixed in v2.2.1+ (#60034). Under fractional OS display scaling (125%/150%/175%) or desktop zoom, Chromium stops scrolling ~1-2px short of scrollHeight - clientHeight, which wedged the timeline virtualizer cold-mount settle microtask loop (scrollToEnd <-> resizeItem) when opening a session. Thank you all for the detailed stack samples and root-cause analysis - please update to v2.2.1 or newer (v2.2.2 is current) and let us know if you still see any hangs.
Activity
github-actions commentedon Sep 26, 2026
This issue might be a duplicate of existing issues. Please check:\n- #51028: Windows Desktop V2 renderer becomes unresponsive around startup, with V1-to-V2 store migration also noted.\n- #36379: Desktop renderer hangs when opening sessions with very large message histories.
HexStan commentedon Sep 26, 2026
Additional Note: This issue also occurs even with sessions created after upgrading to V2.
HexStan commentedon Sep 26, 2026
Analysis of the attached debug bundle (
opencode-debug-20260926T001640.zip)I went through the logs from the debug export and sharing the findings in case they help triage.
The freeze is renderer-side, not backend/service-side
main.logis clean in every session: startup, v2 CLI/service startup, and the V1→V2 data migration all complete normally.server-1/opencode.log(~62k lines) shows nothing at the freeze timestamps; its only ERROR entries are from June and unrelated (aborted runs).window.logasrenderer unresponsivefor the main window.The unresponsive events fire exactly when a session is opened
In 5 of the 14 captured sessions,
window.logloggedrenderer unresponsive— each one ~20 s after app start, i.e. right when the first session was opened (times below are local):app starting(main.log)renderer unresponsive(window.log)Sampled stacks all land in the message list's stick-to-bottom virtualizer path
The
renderer unresponsive samplescaptured by the main process always point at the same code path — a virtualized list (looks like TanStack Virtual) performingscrollToEndon mount/measurement:Other samples enter the same class from different entry points:
Ba.scheduleScrollReconcile,Ba.getOffsetForIndex,P.resizeItem. Bundle hashes differ between builds (route-CDROkuzn.js,route-D7t6Qi_B.js,route-CHhjG5_X.js) but the offsets are identical, so it is the same code across 2.0.x.renderer.log shows a ResizeObserver storm
Sessions that froze show bursts of
ResizeObserver loop completed with undelivered notifications, up to 248 lines in a single session:One possibly relevant detail: renderer.log starts with
Slow network is detected. … Fallback font will be used while loading: oc://renderer/assets/Inter.ttf. If the webfont swaps in after the list has already measured and scrolled, item heights change post-measurement — exactly the kind of event that would kick off a measure → scroll → measure loop.How this explains the reported symptoms
Relation to existing issues
This looks like the same family as #33712, #34289, #34038, #37997, #38296, #43355, #48633. One difference that may be useful for triage: in my captures the sampled stacks sit in the session message list virtualizer (
scrollToEndstick-to-bottom), not in the composer-region observers analyzed in #33712. Also note PR #44883 only suppresses the ResizeObserver log noise — the freeze itself still reproduces on 2.0.18.Happy to provide additional logs if needed.
natsforai-lab commentedon Oct 19, 2026
Additional reproduction on Windows 11 with desktop 2.0.32 (latest per the updater; fresh NSIS install).
Environment
PRAGMA quick_check= ok) — this is not a corrupt-store problemSymptom
The renderer becomes unresponsive 17–18 seconds after launch, while the first session's message list is rendering. The main-process watchdog logs
renderer unresponsiveand then collects stack samples; the UI stays wedged and has to be force-killed.Occurrences on 2026-10-19 (local time, UTC+5:30), each on a fresh launch:
Two consecutive launches froze exactly 17 s and 18 s after process start. A later launch restored the same session without freezing, so this is timing-dependent, not purely data-dependent. The session opened was moderate in size (~550 messages, ~1,600 parts).
Evidence
window.log— renderer unresponsive samples (repeating):Same measure/resize ↔ scroll-to-end loop in the message-list virtualizer described above (
resizeItem,_scrollToOffset,scrollToIndex).renderer.logalso contains repeated:and at startup (before the first session renders):
which is consistent with the late-webfont-swap theory (items re-measured after the first layout pass).
Notes
opencode-debug-20261019T162611.zip, ~500 KB) if useful.natsforai-lab commentedon Oct 19, 2026
Root cause found + a working local fix (2.0.32, Windows)
Following up on the earlier evidence dump: the hang is not GPU, not the session data, and not the DB. It is a chat virtualizer microtask busy-loop in the renderer.
What the watchdog samples show
The Electron "renderer unresponsive" stacks always land in the same two places (bundled renderer asset
route-BYzALZ62.js):The loop
je()(the tail/measure pass) queues aqueueMicrotaskthat measures every mounted chat row through the overriddenM.resizeItem, and the resize-apply microtask ends by callingke()(tail auto-scroll) and thenje()again. Each iteration mounts/measures/scrolled content that queues another microtask. Because the chain never yields to the event loop, timers never run — including whatever marks markdown blocksdata-markdown-ready. The tail mode only exits when everything is measured and no markdown block is pending (ce.querySelector('[data-component="markdown"]:not([data-markdown-ready])')), so the pane staysvisibility: hidden(the blank window) while memory climbs to 1–3 GB.Throttling
MutationObserver/ResizeObserverfrom the outside does not help — the loop is driven by microtasks, not observer delivery.Local fix (one line in the renderer bundle)
Debounce the measure microtask so the cycle can never run tighter than 150 ms and always yields to the event loop:
Result on the same machine and app build: an 800k-token session (529 messages, the same class of session that froze before) renders, scrolls and stays responsive; renderer idles around 70 MB heap / ~0% CPU, and the chat pane becomes visible in about a second. Cold starts no longer hang.
Happily re-testing any official fix — but the underlying issue looks like the tail-mode completion condition (markdown-ready + measurement settling) can be starved by the measurement microtask chain itself, so a yield/debounce in that path (or dropping
visibility:hiddenwhile waiting) would be the place to patch upstream.opencodejr commentedon Oct 28, 2026
Thanks for the detailed report and the log analysis, and thanks to @natsforai-lab for the extra reproduction on 2.0.32.
I couldn't try to reproduce this here: it needs the desktop app on Windows, and the sandbox I run in is headless Linux, so a maintainer with that setup will need to confirm it.
The code path in your stack samples is still on the current
devbranch, in the session timeline's 'scroll to the bottom on open' handling. That fits the measure → scroll → measure loop you and @natsforai-lab described. Your timings, stack samples and the note that the debounce workaround stops the hang should help whoever looks at it.Related issues (none of them looks like the same cause):
Hona commentedon Oct 30, 2026
Fixed in v2.2.1+ (#60034). Under fractional OS display scaling (125%/150%/175%) or desktop zoom, Chromium stops scrolling ~1-2px short of
scrollHeight - clientHeight, which wedged the timeline virtualizer cold-mount settle microtask loop (scrollToEnd<->resizeItem) when opening a session. Thank you all for the detailed stack samples and root-cause analysis - please update to v2.2.1 or newer (v2.2.2 is current) and let us know if you still see any hangs.