microsoft / microsoft/vscode

Agents renderer OOM: unbounded workspaceFileCount telemetry search materializes every file

Open
#325,919 0 comments 0 reactions 1 assignee Claimed by @osortega View on GitHub
Dominant language
TypeScript
Stars
193k
Forks
42.4k
PR merge metrics
PR metrics pending

Description

Does this issue occur when all extensions are disabled?: Not tested. The direct trigger is in the core Sessions contribution, and it reproduces with two different agent providers.

- VS Code Version: 1.128.1 (`5264f2156cbcd7aea5fd004d29eaa10209155d66`), arm64
- OS Version: macOS 26.5.2, Apple Silicon, 36 GB RAM
- Telemetry setting: `telemetry.telemetryLevel: "off"`
- Feature: standalone Agents/Sessions window

## Summary

Sending a foreground message in the Agents/Sessions window can start an unbounded recursive file search solely to compute the `workspaceFileCount` telemetry field. When an agent session uses a large directory as its workspace (in this reproduction, `$HOME` with approximately 1.85 million non-excluded files), every matching file URI is streamed from the extension host to the renderer and retained until the search completes. The renderer V8 heap grows by several gigabytes and terminates with an out-of-memory crash.

This also occurs when usage telemetry is disabled. The eventual telemetry log call becomes a no-op, but the expensive collection has already happened.

## Steps to Reproduce

1. Open the standalone Agents/Sessions window with no normal workspace folder open.
2. Create a new agent session whose effective working directory is a large directory such as `$HOME`.
3. Send any short foreground message.
4. Observe the renderer memory while the provider is processing the request.

## Expected Behavior

- The response renders normally.
- Telemetry-only data collection does not run when usage telemetry is disabled.
- A file count never requires materializing every matching URI in the renderer.

## Actual Behavior

- `SessionsTelemetryContribution.onWillSendRequest` starts `_startWorkspaceFileCountFetch(...)` before the provider request completes.
- `_computeWorkspaceFileCount(...)` calls `fileSearch` with `filePattern: ''` and no `maxResults`.
- The extension host runs an `rg --files` search over the session workspace and sends all matches to the renderer.
- `RemoteSearchProvider` stores every revived URI in `SearchOperation.matches`, then converts the complete map to an array even though the caller only needs `results.length`.
- In this reproduction, renderer heap use increased from approximately 76 MiB to 3.56 GiB in about 18 seconds. DOM nodes and event-listener counts remained roughly flat.
- The provider completed and persisted its final response before the renderer crashed. Reloading the window could then reveal the already-completed response, which explains an associated “first response is blank, reload shows it” symptom.
- The macOS crash report recorded `Code Helper (Renderer)`, `EXC_BREAKPOINT` / `SIGTRAP`, termination code 5. Allocation sampling was dominated by extension-host search-result RPC deserialization and URI revival.

Sanitized memory samples from the renderer:

| Time relative to send | Heap used | JS heap used | DOM nodes | JS listeners |
|---:|---:|---:|---:|---:|
| before send | 76.4 MiB | 76.4 MiB | 4,103 | 5,618 |
| +11 s | 1,007.1 MiB | 903.9 MiB | 2,870 | 2,834 |
| +20 s | 3,166.3 MiB | 2,950.8 MiB | 2,717 | 2,834 |
| +23 s | 3,557.2 MiB | 3,217.6 MiB | 2,694 | 2,893 |

The dominant allocation stack was:

```text
deserializeRequestJSONArgs
→ $handleFileMatch
→ handleFindMatch / addMatch
→ URI.revive / URI.toJSON
```

## Relevant Source

The behavior is present in both the installed 1.128.1 source and current `main` as of this report:

- The foreground send hook starts the count unconditionally: [`sessionsTelemetry.contribution.ts#L68-L74`](https://github.com/microsoft/vscode/blob/dba8c3aacec6d7e4d84a75c978cc3479cb777388/src/vs/sessions/contrib/sessions/browser/sessionsTelemetry.contribution.ts#L68-L74)
- The count performs an unbounded file search: [`sessionsTelemetry.contribution.ts#L628-L636`](https://github.com/microsoft/vscode/blob/dba8c3aacec6d7e4d84a75c978cc3479cb777388/src/vs/sessions/contrib/sessions/browser/sessionsTelemetry.contribution.ts#L628-L636)
- Search results are accumulated in the renderer: [`mainThreadSearch.ts#L175-L205`](https://github.com/microsoft/vscode/blob/dba8c3aacec6d7e4d84a75c978cc3479cb777388/src/vs/workbench/api/browser/mainThreadSearch.ts#L175-L205)
- Missing `maxResults` becomes unlimited: [`fileSearch.ts#L64-L70`](https://github.com/microsoft/vscode/blob/dba8c3aacec6d7e4d84a75c978cc3479cb777388/src/vs/workbench/services/search/node/fileSearch.ts#L64-L70)

There also appears to be a cache issue: `onWillSendRequest` calls `_startWorkspaceFileCountFetch` directly. The in-flight entry is deleted when the scan completes, while the completed result is cached by session only later through `_getOrFetchWorkspaceFileCount`. A later foreground send can therefore start another workspace scan after the first one has completed.

The `workspaceFileCount` collection was introduced by [`33c7eb7`](https://github.com/microsoft/vscode/commit/33c7eb74f51e638d573fc3fb1f4c0045c25987a2).

## Suggested Fix

1. Do not collect `workspaceFileCount` unless the active telemetry level permits usage telemetry.
2. Do not materialize every match in the renderer just to compute a count. Use an extension-host-side count, or apply a strict finite `maxResults` and report a capped/bucketed value.
3. Check a workspace-level completed cache before starting another foreground scan.
4. Add regression coverage for a HOME-sized workspace and for `telemetry.telemetryLevel: "off"`.

## Privacy Note

I have intentionally not attached the raw heap snapshot, allocation profile, agent protocol logs, or crash archive because they can contain private workspace paths, prompts, responses, and tool payloads. The measurements and stack information above were extracted and sanitized from those artifacts.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.