Skip to content

Renderer unresponsive (6-7s freeze) in execEditLength when computing large file diffs #32853

Closed as not planned

Description

@Domovikx

Description

Description:
Renderer becomes unresponsive for 6-7 seconds when computing file diffs in a session with large files. The hang occurs in the diff algorithm (execEditLength → structuredPatch → createTwoFilesPatch → resolveFileDiff) triggered by CollapsibleRoot components rendering file diffs.

Two consecutive sessions crashed the same way (17:18 and 17:35). The renderer recovered on its own each time (~6s), but the app is unusable during the freeze.

Full debug logs attached.

OpenCode version:
1.17.8 (packaged, win32 x64)

Steps to reproduce:

  1. Open a session that contains a file diff with many changes or a very large file
  2. The CollapsibleRoot component tries to compute structuredPatch → execEditLength
  3. The O(n*m) diff algorithm blocks the main thread for 6+ seconds
  4. Electron marks the window as "renderer unresponsive"

Operating System:
Windows 11

Terminal:
Windows Terminal

Plugins

OpenCode version

1.17.8 (packaged, win32 x64)

Steps to reproduce

  1. Open a session that contains a file diff with many changes or a very large file
  2. The CollapsibleRoot component tries to compute structuredPatch → execEditLength
  3. The O(n*m) diff algorithm blocks the main thread for 6+ seconds
  4. Electron marks the window as "renderer unresponsive"

opencode-debug-20260618T143520.zip

Screenshot and/or share link

No response

Operating System

Windows 11

Terminal

Windows Terminal

Activity

  1. github-actions commented on Jun 18, 2026

    @github-actions
    Contributor

    This issue might be a duplicate of existing issues. Please check:

    If your issue is distinct from the above, please add context explaining how it differs.

  2. rafaelgou commented on Jul 2, 2026

    @rafaelgou

    It seems I have the same issue Opencode GUI on Ubuntu 24.04.

    I used MiMo v2.5 on Opencode TUI to analyse the logs and generate a report. I hope it's useful.

    Full report attached.

    opencode-debug-20260702T130622.zip


    Renderer Unresponsive: Synchronous Diff Computation Blocks UI Thread

    Environment

    Symptoms

    • GUI freezes completely, Electron marks renderer as "unresponsive"
    • Multiple sessions across several days reproduced the same freeze (10+ dump directories in logs)
    • One session recovered after ~6s; others required force-quit
    • ResizeObserver loop completed with undelivered notifications in renderer.log confirms UI thread saturation

    Root Cause

    The diff npm package (used for computing unified diffs) runs synchronously on the renderer main thread inside a SolidJS reactive computation. When a session contains a large file diff, the O(n*m) Myers diff algorithm blocks the main thread for seconds, triggering Electron's unresponsive detector.

    Stack Trace (from window.log)

    renderer unresponsive {
      window: '7ea1ad21-534f-42be-8c90-1c807b0d021c',
      currentURL: 'oc://renderer/index.html'
    }
    
    renderer unresponsive samples
    Window: 7ea1ad21-534f-42be-8c90-1c807b0d021c
    URL: oc://renderer/index.html
    <2>
        at execEditLength (main-C--ziyJW.js:44377:7)
        at LineDiff.diffWithOptionsObj (main-C--ziyJW.js:44426:21)
        at LineDiff.diff (main-C--ziyJW.js:44347:17)
        at diffLines (main-C--ziyJW.js:44577:19)
        at structuredPatch (main-C--ziyJW.js:44619:35)
        at createTwoFilesPatch (main-C--ziyJW.js:44749:22)
        at parseDiffFromFile (main-C--ziyJW.js:44776:32)
        at fileDiffFromContent (main-C--ziyJW.js:137831:10)
        at fileDiffFromPatch (main-C--ziyJW.js:137765:28)
        at resolveFileDiff (main-C--ziyJW.js:137735:47)
        at normalize (main-C--ziyJW.js:137748:15)
        at main-C--ziyJW.js:145033:8
        at Proxy.map (<anonymous>)
        at Object.fn (main-C--ziyJW.js:145032:74)
        at runComputation (main-C--ziyJW.js:487:22)
        at updateComputation (main-C--ziyJW.js:470:3)
        at Object.readSignal (main-C--ziyJW.js:403:67)
        at diff2 (main-C--ziyJW.js:145247:41)
        at diffCanRender (main-C--ziyJW.js:145248:49)
        at get value (main-C--ziyJW.js:145362:32)
        at Array.resolveSources (main-C--ziyJW.js:963:24)
        at isExpanded (main-C--ziyJW.js:116706:48)
        at get open (main-C--ziyJW.js:116721:18)
        at Array.resolveSources (main-C--ziyJW.js:963:24)
        at open (main-C--ziyJW.js:108733:23)
        at access$1 (main-C--ziyJW.js:8319:67)
        at Object.value (main-C--ziyJW.js:9675:18)
        at Object.fn (main-C--ziyJW.js:9647:54)
        at runComputation (main-C--ziyJW.js:487:22)
        at updateComputation (main-C--ziyJW.js:470:3)
        at createMemo (main-C--ziyJW.js:119:3)
        at createControllableSignal$1 (main-C--ziyJW.js:9647:24)
        at createControllableBooleanSignal (main-C--ziyJW.js:9664:31)
        at createDisclosureState (main-C--ziyJW.js:9674:31)
        at CollapsibleRoot$1 (main-C--ziyJW.js:108732:27)
    

    Call Chain Analysis

    The freeze path is:

    1. CollapsibleRoot (file diff collapsible section) mounts
    2. createDisclosureState → createControllableBooleanSignal creates reactive state
    3. isExpanded getter triggers diffCanRender → diff2
    4. diff2 reads resolveSources signal which calls resolveFileDiff → normalize
    5. normalize calls fileDiffFromContent → parseDiffFromFile → createTwoFilesPatch
    6. createTwoFilesPatch → structuredPatch → diffLines → LineDiff.diff
    7. LineDiff.diff runs execEditLength — the O(n*m) Myers algorithm — synchronously on the main thread

    The entire diff computation is wrapped in runComputation, meaning it re-executes on any reactive dependency change with no debouncing, no lazy evaluation, and no web worker offloading.

    Reproducibility

    This exact stack trace appeared in 10+ separate session dumps across Jun 30 – Jul 2, 2026:

    Session Date Result
    20260630T122440 Jun 30 renderer.log present
    20260701T144943 Jul 1 14:49 crash.log
    20260701T165125 Jul 1 16:51 crash.log
    20260701T170005 Jul 1 17:00 crash.log
    20260701T174224 Jul 1 17:42 crash.log
    20260701T233829 Jul 1 23:38 crash.log
    20260701T234841 Jul 1 23:48 window.log: unresponsive, same stack
    20260701T234908 Jul 1 23:49 crash.log
    20260702T000115 Jul 2 00:01 crash.log
    20260702T000134 Jul 2 00:01 crash.log
    20260702T000228 Jul 2 00:02 window.log: unresponsive (recovered)
    20260702T002125 Jul 2 00:21 crash.log
    20260702T002211 Jul 2 00:22 crash.log
    20260702T130558 Jul 2 13:05 window.log: unresponsive, same stack

    Suggested Fix Directions

    1. Offload diff computation to a Web Worker — move createTwoFilesPatch / structuredPatch off the main thread entirely
    2. Lazy/deferred evaluation — only compute the diff when the collapsible section is expanded, not eagerly in a reactive computation
    3. Debounce diff computation — avoid recomputing on every reactive dependency change
    4. Virtualize large diffs — render only visible hunks, compute diff per-hunk on demand
    5. Size guard — skip visual diff for files above a threshold (e.g. >10k lines), show a "file too large for diff" message instead
  3. github-actions commented on Sep 1, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

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

Metadata

Metadata

Assignees

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