microsoft / microsoft/vscode

Copilot Chat: “InstantiationService has been disposed” thrown from PromptRenderer.render during long sessions

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

Description

### Type of issue
Bug

### Steps to Reproduce
1. Keep a Copilot Chat session open for hours with heavy message churn (many tool calls per turn, long agent loops, large context).
2. Continue driving turns; interrupt/cancel some mid-flight; open/close chat windows.
3. After enough churn, the render pipeline throws `InstantiationService has been disposed` and the extension host crashes.

Recurred ~10× in one evening on the same install; same stack signature each time.

### Actual Behavior
Extension host crash. Session becomes unusable until VS Code (or the extension host) is restarted.

### Expected Behavior
No crash. Cancellation or parent-service dispose during an in-flight render should short-circuit cleanly or surface as a cancellation error to the caller — not escape from `InstantiationService._throwIfDisposed` and take down the render pipeline.

### Stack signature

Error: InstantiationService has been disposed
at ._throwIfDisposed (.../copilot/dist/extension.js)
...
at async .render (.../copilot/dist/extension.js)

Identical `_throwIfDisposed → async .render` shape on every recurrence.

### Environment
- OS: macOS
- VS Code: 1.136.1 (Universal)
- GitHub Copilot Chat: 1.0.81-0

### Diagnostic pointer
The vendored `InstantiationService` at [extensions/copilot/src/util/vs/platform/instantiation/common/instantiationService.ts](https://github.com/microsoft/vscode/blob/main/extensions/copilot/src/util/vs/platform/instantiation/common/instantiationService.ts) throws from `_throwIfDisposed` on `createChild` / `createInstance` / `invokeFunction`. The most plausible async `.render` site in that bundle is [`PromptRenderer.render`](https://github.com/microsoft/vscode/blob/main/extensions/copilot/src/extension/prompts/node/base/promptRenderer.ts), which:

- creates `hydratedInstaService = instantiationService.createChild(...)` per render,
- awaits `super.render(progress, token)` — an async tree walk from `@vscode/prompt-tsx` that keeps calling `createElement` → `_instantiationService.createInstance(...)` between awaits,
- calls `this._instantiationService.dispose()` at the end (**not** in a `finally`).

Two candidate races consistent with the stack:
1. Parent `InstantiationService` disposes while `super.render` is still walking → the hydrated child is cascade-disposed → the next `createElement` throws.
2. `renderer.render(...)` returns and disposes the child; a subsequent use of the same renderer (e.g. `countTokens()`, or a retained reference) touches the disposed service.

Additionally, `super.render` throwing skips the trailing `this._instantiationService.dispose()` — the hydrated child leaks (addressed by an accompanying PR).

### Related
- Same error class, sibling site fixed in settings editor: #330277 / #330344 (principle: guard at the async re-entry boundary in the owning object, not inside `InstantiationService`).
- Closest open shape-match for chat: #333132.
- Recent unrelated site fixed: #333537 / #333540.

### Workaround
"Developer: Restart Extension Host" clears the state; the crash re-emerges under heavy load.

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.