Skip to content

fix(opencode): unbounded memory growth during active usage#16346

Open
GooseG17 wants to merge 1 commit intoanomalyco:devfrom
GooseG17:fix/memory-leak-gc
Open

fix(opencode): unbounded memory growth during active usage#16346
GooseG17 wants to merge 1 commit intoanomalyco:devfrom
GooseG17:fix/memory-leak-gc

Conversation

@GooseG17
Copy link

@GooseG17 GooseG17 commented Mar 6, 2026

Issue for this PR

Fixes #13230
Also relates to #11399, #9140

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

It fixes the memory leaks that caused opencode to increase its virtual memory at about 2.3 GB/min, leading to application, or even system, crashes.

Five leak/retention points contribute to this:

  1. plugin/index.tsBus.subscribeAll() is called without storing the unsubscribe handle. Each init() call stacks another permanent wildcard subscriber. Fixed by storing and calling unsubscribe before re-subscribing.

  2. session/prompt.ts — The full msgs array stays alive during processor.process() after it's no longer needed. Now released immediately after building model messages, and Bun.gc(true) is called after each turn to let JSC compact the heap.

  3. session/processor.tstoolcalls, reasoningMap, and currentText hold references across retries and after processing finishes. Now cleared on completion, error, and retry paths. Bun.gc(false) added between multi-tool steps.

  4. lsp/client.tsdiagnostics Map and files object grow with every unique file path and are never cleared. Now cleared on shutdown.

  5. lsp/index.tsclients, broken, spawning collections are never cleaned up on teardown. Now cleared.

The Bun.gc() calls are wrapped in try/catch so they're no-ops if the API isn't available.

How did you verify your code works?

Monitored memory via /proc/<pid>/status (VmSize, VmData, VmRSS) and /proc/<pid>/maps line counts during active streaming sessions before and after the fix. Before: +2.3 GB/min virtual growth, mapping count climbing ~1,278/min. After: virtual memory stabilized and RSS stayed flat across multiple extended sessions. The system no longer OOM-killed after hours of use with multiple opencode instances.

Screenshots / recordings

N/A — not a UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Addresses multiple reports of OpenCode processes growing to 100+ GB virtual
memory, triggering OOM kills and system crashes (anomalyco#13230, anomalyco#11399, anomalyco#7046, anomalyco#9140).

Root cause: Bun/JSC reserves virtual memory regions that accumulate without
bound during active LLM streaming and tool execution. Combined with several
code-level leaks, the process grows at ~2.3 GB/min of virtual address space
until the kernel OOM killer intervenes.

Fixes:

1. plugin/index.ts: Bus.subscribeAll() was called without storing the
   unsubscribe function. Each call to init() added a permanent wildcard
   subscriber, causing O(n) callback fan-out per bus event.

2. session/prompt.ts: The full conversation history (msgs array) was kept
   alive during processor.process() after model message conversion. Now
   released immediately after use. Added Bun.gc(true) after each processing
   turn and at loop exit to force JSC heap compaction.

3. session/processor.ts: Hoisted currentText/reasoningMap outside try block
   for proper cleanup on both success and error paths. Clear toolcalls record
   after processing. Added Bun.gc(false) between steps to curb growth during
   multi-tool-call sequences. Release stream references before retry.

4. lsp/client.ts: diagnostics Map and files object grew with every unique
   file path and were never cleared. Now cleared on shutdown().

5. lsp/index.ts: clients array, broken Set, and spawning Map were left
   populated after teardown, preventing GC. Now cleared.
@github-actions github-actions bot added needs:compliance This means the issue will auto-close after 2 hours. needs:issue labels Mar 6, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Mar 6, 2026

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 6, 2026

The following comment was made by an LLM, it may be inaccurate:

I found several related PRs that address similar memory leak issues:

Potential Related PRs:

  1. PR fix: resolve memory leak issues across multiple subsystems #14650 - "fix: resolve memory leak issues across multiple subsystems"

    • Likely addresses similar multi-point memory leak issues
  2. PR fix: prevent memory leaks from SSE streams, LSP, Bus, and process cleanup #15646 - "fix: prevent memory leaks from SSE streams, LSP, Bus, and process cleanup"

    • Directly overlaps with this PR's scope (LSP cleanup, Bus leaks, stream cleanup)
  3. PR fix(core): add dispose functions to prevent subscription memory leaks #7914 - "fix(core): add dispose functions to prevent subscription memory leaks"

    • Addresses subscription/Bus-related memory leaks mentioned in current PR

These PRs are related because they target memory leak issues in the same subsystems: Bus subscriptions, LSP client state, and stream/processor cleanup. PR #15646 appears most directly related as it covers LSP, Bus, and stream cleanup—the same components addressed in PR #16346.

@GooseG17 GooseG17 changed the title fix: memory leak - unbounded virtual memory growth during active usage fix(opencode): unbounded memory growth during active usage Mar 6, 2026
@github-actions github-actions bot removed needs:compliance This means the issue will auto-close after 2 hours. needs:issue labels Mar 6, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Mar 6, 2026

Thanks for updating your PR! It now meets our contributing guidelines. 👍

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Critical] Memory leak causes kernel soft lockups (356s, 7/8 CPUs), OOM kills (111GB virt/21GB RSS), and total system death on Linux

1 participant