Skip to content

[Unhandled Error] potential listener LEAK detected, popular — search/searchResultsView / toolbar → menuService #308255

Description

@vs-code-engineering

Error Message

potential listener LEAK detected, popular

Stack Trace

    at a.create (./src/vs/base/common/event.ts:1062:14)
    at Pz._event [as onDidChange] (./src/vs/base/common/event.ts:1262:33)
    at Object.u [as onWillAddFirstListener] (./src/vs/platform/actions/common/menuService.ts:437:0)
    at ZCe._event [as onDidChange] (./src/vs/base/common/event.ts:1271:19)
    at new or (./src/vs/platform/actions/browser/toolbar.ts:377:0)
    at a._createInstance (./src/vs/platform/instantiation/common/instantiationService.ts:162:17)
    at a.createInstance (./src/vs/platform/instantiation/common/instantiationService.ts:128:17)
    at e6.renderTemplate (./src/vs/workbench/contrib/search/browser/searchResultsView.ts:328:0)
    at mli.renderTemplate (./src/vs/base/browser/ui/tree/asyncDataTree.ts:1439:0)
    at dxt.renderTemplate (./src/vs/base/browser/ui/tree/objectTree.ts:122:29)
    at a.renderTemplate (./src/vs/base/browser/ui/tree/abstractTree.ts:431:0)
    at (anonymous) (./src/vs/base/browser/ui/list/listWidget.ts:1273:35)
    at tri.renderTemplate (./src/vs/base/browser/ui/list/listWidget.ts:1273:24)
    at Byt.alloc (./src/vs/base/browser/ui/list/rowCache.ts:40:33)
    at gR.insertItemInDOM (./src/vs/base/browser/ui/list/listView.ts:962:30)
    at gR._splice (./src/vs/base/browser/ui/list/listView.ts:725:9)
    at gR.splice (./src/vs/base/browser/ui/list/listView.ts:626:15)
    at (anonymous) (./src/vs/base/browser/ui/list/splice.ts:17:34)
    at Pyt.splice (./src/vs/base/browser/ui/list/splice.ts:17:19)
    at (anonymous) (./src/vs/base/browser/ui/list/listWidget.ts:1621:56)

Raw Stack Trace (minified)
Error     at a.create (out/vs/workbench/workbench.desktop.main.js:403:18382)     at Pz._event [as onDidChange] (out/vs/workbench/workbench.desktop.main.js:405:1807)     at Object.u [as onWillAddFirstListener] (out/vs/workbench/workbench.desktop.main.js:852:136431)     at ZCe._event [as onDidChange] (out/vs/workbench/workbench.desktop.main.js:405:2074)     at new or (out/vs/workbench/workbench.desktop.main.js:852:141276)     at a._createInstance (out/vs/workbench/workbench.desktop.main.js:1899:2000)     at a.createInstance (out/vs/workbench/workbench.desktop.main.js:1899:1440)     at e6.renderTemplate (out/vs/workbench/workbench.desktop.main.js:3534:11096)     at mli.renderTemplate (out/vs/workbench/workbench.desktop.main.js:861:43105)     at dxt.renderTemplate (out/vs/workbench/workbench.desktop.main.js:861:18655)     at a.renderTemplate (out/vs/workbench/workbench.desktop.main.js:860:17232)     at out/vs/workbench/workbench.desktop.main.js:728:2084     at Array.map (<anonymous>)     at tri.renderTemplate (out/vs/workbench/workbench.desktop.main.js:728:2075)     at Byt.alloc (out/vs/workbench/workbench.desktop.main.js:685:5677)     at gR.insertItemInDOM (out/vs/workbench/workbench.desktop.main.js:685:21722)     at gR._splice (out/vs/workbench/workbench.desktop.main.js:685:17727)     at gR.splice (out/vs/workbench/workbench.desktop.main.js:685:15999)     at out/vs/workbench/workbench.desktop.main.js:683:125     at Array.forEach (<anonymous>)     at Pyt.splice (out/vs/workbench/workbench.desktop.main.js:683:112)     at out/vs/workbench/workbench.desktop.main.js:728:8948     at eO.bufferEvents (out/vs/workbench/workbench.desktop.main.js:405:6915)     at Yai.splice (out/vs/workbench/workbench.desktop.main.js:728:8915)     at Yai.splice (out/vs/workbench/workbench.desktop.main.js:860:48361)     at YSe.value (out/vs/workbench/workbench.desktop.main.js:861:4465)     at E._deliver (out/vs/workbench/workbench.desktop.main.js:405:3066)     at E.fire (out/vs/workbench/workbench.desktop.main.js:405:3385)     at YSe.value (out/vs/workbench/workbench.desktop.main.js:403:11566)     at E._deliver (out/vs/workbench/workbench.desktop.main.js:405:3066)     at E._deliverQueue (out/vs/workbench/workbench.desktop.main.js:405:3155)     at E.fire (out/vs/workbench/workbench.desktop.main.js:405:3490)     at oxt.spliceSimple (out/vs/workbench/workbench.desktop.main.js:860:4339)     at oxt.splice (out/vs/workbench/workbench.desktop.main.js:860:2413)     at Jz._setChildren (out/vs/workbench/workbench.desktop.main.js:861:7335)     at Jz.setChildren (out/vs/workbench/workbench.desktop.main.js:861:6755)     at Zai._setChildren (out/vs/workbench/workbench.desktop.main.js:861:13109)     at Zai.setChildren (out/vs/workbench/workbench.desktop.main.js:861:11997)     at cxt.setChildren (out/vs/workbench/workbench.desktop.main.js:861:16618)     at Nxe.setChildren (out/vs/workbench/workbench.desktop.main.js:861:21074)     at sy.render (out/vs/workbench/workbench.desktop.main.js:861:41132)     at sy.render (out/vs/workbench/workbench.desktop.main.js:861:45662)     at sy.refreshAndRenderNode (out/vs/workbench/workbench.desktop.main.js:861:37734)     at async sy._updateChildren (out/vs/workbench/workbench.desktop.main.js:861:33933)     at async sy.updateChildren (out/vs/workbench/workbench.desktop.main.js:861:33429)     at async Hst.refreshTree (out/vs/workbench/workbench.desktop.main.js:3561:2729)

Details

Property Value
Bucket ID 5c4c98d0-4846-6289-96b7-32a064e3ab97
Version 1.115.0-insider
Commit 3d70aab9
Last Seen Sun Apr 05 2026 23:45:49 GMT+0000 (Coordinated Universal Time)
Platforms Windows, Mac, Linux
Product VSCode

This issue was automatically created from the VS Code Errors Dashboard

Activity

  1. vs-code-engineering commented on Apr 7, 2026

    @vs-code-engineering
    Author
  2. vs-code-engineering commented on Apr 7, 2026

    @vs-code-engineering
    ContributorAuthor

    🔍 Error Investigation

    Summary

    The error potential listener LEAK detected, popular fires on the singleton PersistedMenuHideState._onDidChange emitter in menuService.ts. Every MenuImpl that has an active onDidChange listener subscribes to this shared emitter. The search results view creates a MenuWorkbenchToolBar (and thus a MenuImpl) for each template across 4 renderers (TextSearchResultRenderer, FolderMatchRenderer, FileMatchRenderer, MatchRenderer), pushing the total listener count above the global leak threshold of 175. Affects 119+ users across all platforms.

    Culprit Commit

    No single commit in the range 54b695e0...b826afb9 directly modifies the affected files (event.ts, menuService.ts, toolbar.ts, searchResultsView.ts). This regression is a threshold-crossing event: the total number of active MenuImpl instances across the entire application grew past the 175 global leak warning threshold. The 29 commits in the range include multiple Sessions/Agents UI additions that cumulatively add new menus and toolbars to the app, each subscribing to the shared PersistedMenuHideState._onDidChange emitter. The search results view is the "straw that broke the camel's back" — it creates many templates rapidly when rendering results, triggering the leak detection.

    Code Flow

    sequenceDiagram
        participant Search as SearchResultsView<br/>renderTemplate()
        participant Toolbar as MenuWorkbenchToolBar<br/>constructor
        participant MenuImpl as MenuImpl<br/>constructor
        participant HiddenStates as PersistedMenuHideState<br/>._onDidChange (singleton)
        participant LeakMon as LeakageMonitor
    
        Search->>Toolbar: createInstance(MenuWorkbenchToolBar, MenuId.SearchActionMenu)
        Toolbar->>MenuImpl: menuService.createMenu(menuId)
        Toolbar->>MenuImpl: menu.onDidChange(callback)
        Note over MenuImpl: First listener → onWillAddFirstListener
        MenuImpl->>HiddenStates: hiddenStates.onDidChange(callback)
        Note over HiddenStates: ⚠️ Root cause:<br/>Singleton emitter with default<br/>threshold (175), receives one<br/>listener per active MenuImpl
        HiddenStates->>LeakMon: check(stack, listenerCount)
        Note over LeakMon: 💥 listenerCount ≥ 175<br/>Error: "potential listener<br/>LEAK detected, popular"
    
    Loading

    Affected Files

    File Role
    src/vs/platform/actions/common/menuService.ts:59-60 Root cause — PersistedMenuHideState._onDidChange singleton Emitter with no custom leak threshold
    src/vs/platform/actions/common/menuService.ts:437 Each MenuImpl.startLazyListener() subscribes to hiddenStates.onDidChange
    src/vs/platform/actions/browser/toolbar.ts:377 MenuWorkbenchToolBar constructor subscribes to _menu.onDidChange, triggering lazy listener
    src/vs/workbench/contrib/search/browser/searchResultsView.ts:123,227,328,422 4 renderers each create MenuWorkbenchToolBar per template — leak trigger
    src/vs/base/common/event.ts:1008-1034 LeakageMonitor.check() — fires the leak error when listenerCount ≥ threshold
    src/vs/workbench/browser/workbench.ts:135 Sets _globalLeakWarningThreshold to 175

    Repro Steps

    1. Open VS Code Insiders (1.115.0+, commit b826afb9 or later)
    2. Open a workspace with many files (e.g., the VS Code repo itself)
    3. Open the Search view (Ctrl+Shift+F / Cmd+Shift+F)
    4. Perform a search that returns many results (e.g., search for import)
    5. Expand several file matches so many match rows are visible
    6. The leak error fires in telemetry when the total count of MenuImpl instances subscribing to hiddenStates.onDidChange exceeds 175

    The error is more likely to trigger when VS Code has many menus active (editor tabs, sidebar panels, toolbars) in addition to the search results.

    Fix Proposal

    Option A (quick fix) — Increase the leak threshold on the singleton emitter:

    Fix location: src/vs/platform/actions/common/menuService.ts → PersistedMenuHideState class
    Approach: Change line 59 from new Emitter(void)() to new Emitter(void)({ leakWarningThreshold: 500 }). This emitter is a singleton that legitimately receives one listener per active MenuImpl in the entire application, so 175 is too low.

    Option B (structural fix) — Decouple search result templates from per-instance menus:

    Fix location: src/vs/workbench/contrib/search/browser/searchResultsView.ts → all 4 renderTemplate() methods
    Approach: Instead of creating a MenuWorkbenchToolBar (and thus a MenuImpl) per template, share a single menu instance per renderer type. The toolbar can refresh its context on renderElement without needing a dedicated MenuImpl per row. This reduces the listener count on hiddenStates.onDidChange by ~100+.

    Option C (hybrid) — Apply both fixes: raise the threshold to avoid false positives, and refactor search templates for efficiency.

    Recommended Owner

    @bryanchen-d is already assigned (error-telemetry area owner). For the fix itself, @osortega (Search area owner per working-areas.md) is the recommended owner, as the primary fix involves the search results view template pattern. For Option A (menuService threshold), @jrieken (platform/performance owner) may want to weigh in on the appropriate threshold value.

    Generated by errors-investigate · ◷

  3. bryanchen-d commented on Apr 7, 2026

    @bryanchen-d
    Collaborator

    as per analysis, this is more a false alarm:

    The global leak threshold is set to 175 in workbench.ts:135. It just wasn't tuned for a scenario where 4 renderer types each create toolbars across hundreds of search result rows. This is a false positive from too many legitimate subscribers, not an actual leak.

  4. vs-code-engineering commented on Apr 8, 2026

    @vs-code-engineering
    ContributorAuthor

    Related Error Buckets

    These additional error buckets are tracked by this issue (v1.114.0):

    Bucket ID Error Message Version
    18361d63 potential listener LEAK detected, popular 1.114.0

    Stack path: event.ts → menuService.ts:437 → toolbar.ts:377 → instantiationService → searchResultsView.ts:422 — same search results view toolbar listener leak pattern as the primary bucket (different line in searchResultsView.ts but same code path through toolbar initialization).

    Generated by errors-triage · ◷

  5. changed the title [-][Unhandled Error] potential listener LEAK detected, popular[/-] [+][Unhandled Error] potential listener LEAK detected, popular — search/searchResultsView / toolbar → menuService[/+] on Apr 14, 2026
  6. vs-code-engineering commented on Apr 17, 2026

    @vs-code-engineering
    Author
  7. vs-code-engineering commented on Apr 21, 2026

    @vs-code-engineering
    ContributorAuthor

    Related Error Buckets

    These error buckets continue to appear in v1.117.0-insider (previously tracked since v1.115.0-insider):

    Bucket ID Error Message Users Path
    5912c915 potential listener LEAK detected, popular 207 searchResultsView.ts:422 → menuService.ts:437 → toolbar.ts:377
    ccfc3902 potential listener LEAK detected, popular 122 searchResultsView.ts:328 → menuService.ts:437 → toolbar.ts:377
    aa1cb938 potential listener LEAK detected, popular 32 searchResultsView.ts:422 → toolbar.ts:382

    These additional error buckets are tracked by this issue (v1.117.0-insider):

    Bucket ID Error Message Users Path
    634c9a3e potential listener LEAK detected, popular 35 toolbar.ts:382 → codeBlockPart.ts:210 → chatMarkdownContentPart.ts:438 (chat code block)

    All from commit [173f07e5]((insiders.vscode.dev/redacted) (Apr 20 build). The first three are the same search results view / menuService / toolbar pattern. The 634c9a3e bucket is a new triggering path: the toolbar listener leak fired from chat code block rendering instead of search results.

    Generated by errors-regression-scan · ● 15.8M · ◷

  8. vs-code-engineering commented on Apr 22, 2026

    @vs-code-engineering
    ContributorAuthor

    Related Error Buckets

    These additional error buckets are tracked by this issue (v1.116.0):

    Bucket ID Error Message Version
    a0686ebe potential listener LEAK detected, popular 1.116.0

    Stack path: event.ts → menuService.ts:437 → toolbar.ts → searchResultsView.ts (renderTemplate) — same search results view / menuService / toolbar listener leak pattern as the primary bucket (new bucket ID from minification drift on v1.116.0 stable). 89.6K users, 1.2M hits.

    Generated by errors-triage · ● 3.7M · ◷

  9. added
    ai-generatedGenerated by AI automation workflows
    ai-analyzedAI automation workflow has run an analysis of this issue and provided a comment.
    on Apr 28, 2026
  10. vs-code-engineering commented on Aug 11, 2026

    @vs-code-engineering
    ContributorAuthor

    Related Error Buckets

    These error buckets continue to appear in v1.132.0 (previously tracked since v1.114.0):

    Bucket Error Message Version
    18361d63 unhandlederror-potential listener LEAK detected, popular 1.132.0

    This is a continuation of the previously-tracked listener leak, not a new regression.

    Generated by errors-triage · opus48 · 110.7 AIC · ⌖ 10.1 AIC · ⊞ 10.5K · ◷

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

Metadata

Metadata

Labels

ai-analyzedAI automation workflow has run an analysis of this issue and provided a comment.ai-generatedGenerated by AI automation workflowsbugIssue identified by VS Code Team member as probable bugerror-telemetryVS Code - Issues generated by telemetryrecent-regression

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions