Memory leak: Unbounded caches grow without limit #6631

Open
opened 2026-02-16 18:04:48 -05:00 by yindo · 1 comment
Owner

Originally created by @sauerdaniel on GitHub (Jan 17, 2026).

Originally assigned to: @thdxr on GitHub.

Problem

Several internal caches in OpenCode use standard Map objects without size limits. Over long-running sessions, these caches can grow without bound, contributing to memory issues like those reported in #5363.

Affected Caches

  1. Instance cache (project/instance.ts) - Caches project instances by directory
  2. Provider SDK cache (provider/provider.ts) - Caches loaded SDK instances
  3. LSP spawning cache (lsp/index.ts) - Tracks LSP server spawn promises

Code Example

// Current: unbounded Map that grows forever
const cache = new Map<string, Context>()

// No eviction when cache gets large
cache.set(directory, context)

Impact

  • Memory usage grows continuously over time
  • Long-running sessions can consume excessive RAM (70GB+ reported in #5363)
  • No mechanism to evict stale entries
  • Opening many directories causes unbounded growth

Relates to #5363

Expected Behavior

Caches should have bounded size with LRU eviction:

const cache = createLruCache<string, Context>({
  maxEntries: 20,
  onEvict: (key, value) => {
    // Clean up evicted entry
    value.dispose()
  }
})

Proposed Solution

Create a bounded LRU (Least Recently Used) cache utility that:

  • Limits maximum entries with configurable maxEntries
  • Automatically evicts least-recently-used entries when limit is reached
  • Provides onEvict callback for cleanup when entries are removed
  • Maintains Map-like interface for drop-in replacement
Originally created by @sauerdaniel on GitHub (Jan 17, 2026). Originally assigned to: @thdxr on GitHub. ## Problem Several internal caches in OpenCode use standard `Map` objects without size limits. Over long-running sessions, these caches can grow without bound, contributing to memory issues like those reported in #5363. ### Affected Caches 1. **Instance cache** (`project/instance.ts`) - Caches project instances by directory 2. **Provider SDK cache** (`provider/provider.ts`) - Caches loaded SDK instances 3. **LSP spawning cache** (`lsp/index.ts`) - Tracks LSP server spawn promises ### Code Example ```typescript // Current: unbounded Map that grows forever const cache = new Map<string, Context>() // No eviction when cache gets large cache.set(directory, context) ``` ### Impact - Memory usage grows continuously over time - Long-running sessions can consume excessive RAM (70GB+ reported in #5363) - No mechanism to evict stale entries - Opening many directories causes unbounded growth Relates to #5363 ## Expected Behavior Caches should have bounded size with LRU eviction: ```typescript const cache = createLruCache<string, Context>({ maxEntries: 20, onEvict: (key, value) => { // Clean up evicted entry value.dispose() } }) ``` ## Proposed Solution Create a bounded LRU (Least Recently Used) cache utility that: - Limits maximum entries with configurable `maxEntries` - Automatically evicts least-recently-used entries when limit is reached - Provides `onEvict` callback for cleanup when entries are removed - Maintains Map-like interface for drop-in replacement
yindo added the perf label 2026-02-16 18:04:48 -05:00
Author
Owner

@github-actions[bot] commented on GitHub (Jan 17, 2026):

This issue might be a duplicate of or closely related to existing issues. Please check:

  • #5363: "opencode eating 70gb of memory?" - Direct memory exhaustion report that this issue addresses
  • #8947: "[FEATURE]: TUI whole and LSP memory limits as part of configuration" - Requests memory limiting capabilities to contain memory growth
  • #8887: "[BUG] Snapshot module ignores 'watcher.ignore' config, causing excessive disk usage and performance degradation" - Related performance issue where unbounded tracking causes resource exhaustion
  • #8577: "Snapshot feature needs safeguards for large directories" - Another snapshot-related resource exhaustion issue
  • #9136: "fix(test): prevent memory and resource leaks in test infrastructure" - Addresses similar unbounded resource accumulation pattern in tests

The unbounded cache pattern described in this issue is a root cause of the memory issues mentioned in #5363 and #8947, and similar patterns appear in the snapshot and test infrastructure.

@github-actions[bot] commented on GitHub (Jan 17, 2026): This issue might be a duplicate of or closely related to existing issues. Please check: - #5363: "opencode eating 70gb of memory?" - Direct memory exhaustion report that this issue addresses - #8947: "[FEATURE]: TUI whole and LSP memory limits as part of configuration" - Requests memory limiting capabilities to contain memory growth - #8887: "[BUG] Snapshot module ignores 'watcher.ignore' config, causing excessive disk usage and performance degradation" - Related performance issue where unbounded tracking causes resource exhaustion - #8577: "Snapshot feature needs safeguards for large directories" - Another snapshot-related resource exhaustion issue - #9136: "fix(test): prevent memory and resource leaks in test infrastructure" - Addresses similar unbounded resource accumulation pattern in tests The unbounded cache pattern described in this issue is a root cause of the memory issues mentioned in #5363 and #8947, and similar patterns appear in the snapshot and test infrastructure.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#6631