Skip to content

/vcs/diff can OOM in desktop-layout web UI on umbrella workspaces with many nested git repos #24049

Description

@jeremyakers

Description

I’m seeing repeated OpenCode OOM crashes caused by GET /vcs/diff on a workspace that is an umbrella/meta-repo containing many nested git repos and worktrees.

Important context:

  • I am not intentionally using the review/diff UI.
  • I am using the web UI in a normal desktop browser, not the desktop app.
  • The issue still reproduces with Oh-My-OpenCode disabled.
  • My workspace layout contains many nested repos/worktrees, and OpenCode’s vcsDiff does not handle that layout well.

What I found:

  • In the logs, multiple actual Out of memory failed events happen while one or more GET /vcs/diff requests are in flight.
  • In source, /vcs/diff ultimately builds full-file patches using structuredPatch(..., { context: Number.MAX_SAFE_INTEGER }), which looks extremely memory-heavy.
  • In the app source, the desktop-layout session page can auto-enable review/diff behavior when the file tree is open, even if the review tab was not explicitly opened.

Source references:

  • Route:
    • packages/opencode/src/server/routes/instance/index.ts
  • Implementation:
    • packages/opencode/src/project/vcs.ts
  • Auto-trigger path in app:
    • packages/app/src/pages/session.tsx

Specific code paths:

  • packages/opencode/src/server/routes/instance/index.ts:155-180
  • packages/opencode/src/project/vcs.ts:49-50
  • packages/app/src/pages/session.tsx:586-610
  • packages/app/src/pages/session.tsx:1259-1289

Relevant implementation detail from packages/opencode/src/project/vcs.ts:

const patch = (file: string, before: string, after: string) =>
  formatPatch(structuredPatch(file, file, before, after, "", "", { context: Number.MAX_SAFE_INTEGER }))

And from packages/app/src/pages/session.tsx:

const wantsReview = createMemo(() =>
  isDesktop()
    ? desktopFileTreeOpen() || (desktopReviewOpen() && activeTab() === "review")
    : store.mobileTab === "changes",
)

That means on the desktop-layout web UI, simply having the file tree open appears to be enough to enable diff/review behavior.

Plugins

No response

OpenCode version

1.14.22

Steps to reproduce

  1. Open OpenCode in a desktop browser against a top-level workspace that contains multiple nested git repos/worktrees.
  2. Use the normal session page in the web UI.
  3. Keep the file tree open in the desktop layout.
  4. Allow the session UI to load/refresh.
  5. OpenCode starts issuing GET /vcs/diff requests.
  6. On large enough workspaces, memory usage spikes and OpenCode crashes with OOM.

My workspace shape is roughly:

  • top-level project root
  • multiple nested repos/worktrees underneath for different agents, including active worktrees and nested git roots

This seems important because vcsDiff appears to assume a simpler VCS layout than what an umbrella workspace provides.

Proposed fix

I think there are a few possible fixes, and probably more than one is warranted:

  1. Do not use unbounded patch context in /vcs/diff

    • Replace Number.MAX_SAFE_INTEGER with a bounded context size.
    • This alone may dramatically reduce memory use.
  2. Avoid auto-triggering /vcs/diff just because the file tree is open

    • The desktop-layout web UI should not implicitly enable diff/review behavior unless the user actually opens the review UI or explicitly requests diff state.
  3. Detect and handle nested git repos/worktrees safely

    • Scope diff generation to the active repo only
    • or cheaply short-circuit when nested repo layouts are detected
    • or return a degraded response instead of trying to diff the whole umbrella workspace
  4. Prevent overlapping/redundant /vcs/diff requests

    • The logs show repeated in-flight diff requests.
    • Debouncing, deduping, or canceling stale diff requests would likely help.
  5. Cap total diff output

    • Limit number of files
    • limit total bytes
    • or stop diff generation once a memory-safe threshold is exceeded

Screenshot and/or share link

I uploaded heap snapshots separately, but the strongest evidence here is the route-level log correlation plus the current source code.

Representative log sequence:

  • GET /vcs/diff starts
  • heap warnings begin
  • Out of memory failed
  • the same /vcs/diff request finally completes after a long duration

Example from logs:

  • /vcs/diff starts at 17:54:12
  • heap warnings at 17:54:19 and 17:54:24
  • Out of memory failed at 17:55:42
  • the same /vcs/diff completes at 17:55:42

Operating System

Ubuntu 22.04.5 LTS

Terminal

Web UI for front end, Gnome Terminal / tmux 3.2a for CLI

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