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
Two separate memory leaks keep OpenCode RSS growing without bound:
ACP session manager never frees entries.ACPSessionManager (packages/opencode/src/acp/session.ts:9-72) pushes every new ACP session into a private Map and there is no delete or lifecycle hook tied to cancel. Each ACP IDE reconnect adds another entry plus async subscriptions from setupEventSubscriptions (acp/agent.ts:62-335). The repro script packages/opencode/script/memory/acp-session-leak.ts shows RSS climbing from ~80 MB to ~96 MB after 20k synthetic sessions even with forced GC; heap snapshots (logs/acp-session-leak-*.heapsnapshot) retain all session objects.
Tool compaction does not clear payloads.SessionCompaction.prune only stamps part.state.time.compacted, but the underlying state.output / attachments stay in storage. Every SessionPrompt.prompt reloads the full tool history via MessageV2.stream()/toModelMessage, so sessions with thousands of big tool outputs are re-materialized on every turn. Users report >10 GB RSS after a day because "cleared" tool results are still parsed into JS objects.
Both leaks are captured in spec/memory-leaks.md (benchmark table + repro steps). We need lifecycle cleanup for ACP sessions/subscriptions and real data eviction when compaction marks tool outputs as old.
Tool-output leak: run a long chat session that repeatedly invokes read/edit/bash on large files (or script fake tool parts) and watch process.memoryUsage() / heap snapshots. Even after compaction UI shows "Old tool result content cleared", the backing JSON still contains every output string which gets reloaded on each prompt.
Run with node --expose-gc tool-output-leak.ts (env vars: ITERATIONS, PARTS_PER_ITERATION, OUTPUT_KB, CLEAR_COMPACTED=true, SNAPSHOT_NAME=foo.heapsnapshot).
Mimics MessageV2.stream() repeatedly loading compacted tool parts by keeping all historical outputs in memory; toggle CLEAR_COMPACTED to see how clearing state.output stabilizes RSS.
Feel free to make the gists public or pull them into the repo if that’s easier for others to run.
The acp one isn't that big of an issue tbh each session is pretty minimal but yeah if the protocol has some way of handling a closed connection I should drop the data for it too
Activity
riatzukiza commentedon Nov 14, 2025
Adding direct links to the repro scripts mentioned above for convenience:
ACP session leak harness: https://gist.github.com/riatzukiza/5d64e219d80db584132d638102e1f03a
NODE_OPTIONS=--expose-gc npx tsx acp-session-leak.tsfrom the repo root (or copy intopackages/opencode/script/memory).logs/so you can inspect retained session entries in Chrome DevTools.Tool-output retention stress test: https://gist.github.com/riatzukiza/d40f37809f3cf4141ba2ba5d3360a984
node --expose-gc tool-output-leak.ts(env vars:ITERATIONS,PARTS_PER_ITERATION,OUTPUT_KB,CLEAR_COMPACTED=true,SNAPSHOT_NAME=foo.heapsnapshot).MessageV2.stream()repeatedly loading compacted tool parts by keeping all historical outputs in memory; toggleCLEAR_COMPACTEDto see how clearingstate.outputstabilizes RSS.Feel free to make the gists public or pull them into the repo if that’s easier for others to run.
riatzukiza commentedon Nov 14, 2025
https://opencode.ai/s/V9fpcImD
rekram1-node commentedon Nov 14, 2025
The acp one isn't that big of an issue tbh each session is pretty minimal but yeah if the protocol has some way of handling a closed connection I should drop the data for it too
fix: add cleanup mechanisms to prevent memory leaks in sessions, RPC,…
fix: wire up ACP agent cleanup on connection end to prevent memory leaks
fix: clear tool output and attachments when pruning to prevent memory…