[PR #8252] fix(state): delete key from recordsByKey on instance disposal #12677

Closed
opened 2026-02-16 18:17:34 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/anomalyco/opencode/pull/8252

State: closed
Merged: Yes


Summary

Fix memory leak in State.dispose() where disposed instance keys remain in the parent Map forever.

Fixes #4315
Relates to #3013

Problem

The State namespace uses a two-level Map structure:

  • recordsByKey: Map<string, Map<any, Entry>> - outer Map keyed by instance
  • Inner Map stores state entries for that instance

When State.dispose(key) is called:

  1. It gets the entries Map for the key
  2. Calls dispose on each entry
  3. Calls entries.clear() to empty the inner Map
  4. Bug: Never deletes the key from recordsByKey

This means every disposed instance leaves an empty Map<any, Entry> in recordsByKey, causing unbounded memory growth over the application lifetime.

Solution

Add recordsByKey.delete(key) after entries.clear() to remove the outer Map entry entirely.

entries.clear()
recordsByKey.delete(key)  // <-- Added
await Promise.all(tasks)

Testing

  • Build passes for all platforms
  • Full test suite passes (652 tests, 0 failures)
  • Code-review verified to follow correct cleanup pattern
**Original Pull Request:** https://github.com/anomalyco/opencode/pull/8252 **State:** closed **Merged:** Yes --- ## Summary Fix memory leak in `State.dispose()` where disposed instance keys remain in the parent Map forever. Fixes #4315 Relates to #3013 ## Problem The `State` namespace uses a two-level Map structure: - `recordsByKey: Map<string, Map<any, Entry>>` - outer Map keyed by instance - Inner Map stores state entries for that instance When `State.dispose(key)` is called: 1. It gets the entries Map for the key 2. Calls dispose on each entry 3. Calls `entries.clear()` to empty the inner Map 4. **Bug:** Never deletes the key from `recordsByKey` This means every disposed instance leaves an empty `Map<any, Entry>` in `recordsByKey`, causing unbounded memory growth over the application lifetime. ## Solution Add `recordsByKey.delete(key)` after `entries.clear()` to remove the outer Map entry entirely. ```typescript entries.clear() recordsByKey.delete(key) // <-- Added await Promise.all(tasks) ``` ## Testing - ✅ Build passes for all platforms - ✅ Full test suite passes (652 tests, 0 failures) - Code-review verified to follow correct cleanup pattern
yindo added the pull-request label 2026-02-16 18:17:34 -05:00
yindo closed this issue 2026-02-16 18:17:34 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#12677