Skip to content

fix: guard against disposed model in inline completions (fixes #318217)#318218

Open
vs-code-engineering[bot] wants to merge 1 commit into
mainfrom
fix/inline-completions-disposed-model-318217-2fdf4bbca0e6cca8
Open

fix: guard against disposed model in inline completions (fixes #318217)#318218
vs-code-engineering[bot] wants to merge 1 commit into
mainfrom
fix/inline-completions-disposed-model-318217-2fdf4bbca0e6cca8

Conversation

@vs-code-engineering
Copy link
Copy Markdown
Contributor

🔧 Error Fix

Summary

Error: Model is disposed! thrown from textModel._assertNotDisposed when _inlineSuggestionItems derived observable recomputes during an observable update transaction after the text model has already been disposed.

Impact: Hits across Windows, Mac, and Linux on VS Code 1.121.0 (commit f6cfa2ea). The error fires during command execution (cursor edit) when the observable derivation chain propagates changes through reportChangesendUpdate and reaches the inline completions model’s visibility check.

Fixes #318217
Recommended reviewer: @hediet

Culprit Commit

No single culprit commit identified — this is a latent race condition where the model disposal can occur mid-transaction while derived observables are still recomputing. The inline completions model (inlineCompletionsModel.ts) has been maintained primarily by @hediet.

Code Flow

sequenceDiagram
    participant CMD as EditorCommand
    participant VM as ViewModel
    participant TX as TransactionUpdate
    participant DRV as DerivedObservable
    participant ICM as InlineCompletionsModel
    participant TM as TextModel

    CMD->>VM: executeCommands
    VM->>TX: batchChanges / endUpdate
    TX->>DRV: reportChanges
    DRV->>ICM: _inlineSuggestionItems recompute
    ICM->>TM: isVisible → getValueInRange
    TM-->>TM: _assertNotDisposed → THROWS
Loading

Affected Files

File Role
src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.ts Derived observable calls isVisible on disposed model
src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionIsVisible.ts Calls singleTextRemoveCommonPrefix which hits getValueInRange
src/vs/editor/contrib/inlineCompletions/browser/model/singleTextEditHelpers.ts Calls model.getValueInRange (crash site)
src/vs/editor/common/model/textModel.ts Throws Model is disposed! in _assertNotDisposed

Repro Steps

  1. Open an editor with inline completions active (e.g., Copilot suggestions visible)
  2. Execute a cursor editing command (type, delete) that triggers model disposal (e.g., close the editor tab rapidly during typing)
  3. The observable update transaction propagates through endUpdatereportChanges and reaches _inlineSuggestionItems after the model is already disposed
  4. The derived tries to compute visibility, calling model.getValueInRange() on the disposed model

How the Fix Works

Chosen approach (inlineCompletionsModel.ts:524): Added if (this.textModel.isDisposed()) { return undefined; } as a guard clause at the top of the _inlineSuggestionItems derived computation, after checking for completions but before accessing the model. This prevents the derived from attempting visibility calculations on a disposed model — fixing at the point where the invalid state (disposed model) is first consumed, not at the crash site (textModel._assertNotDisposed). This follows the principle of adding a guard clause upstream of the crash site so the error path is never reached.

Alternatives considered: Wrapping the isVisible call in try/catch would hide the error from telemetry without addressing the root cause. Adding disposal checks inside singleTextRemoveCommonPrefix or inlineCompletionIsVisible would be patching at the crash site rather than the data consumer that initiates the invalid access.

Recommended Owner

@hediet — primary author and maintainer of the inline completions model and observable-based architecture in this area.

Generated by errors-fix · ● 22.4M ·

When the text model is disposed during an observable update transaction,
the _inlineSuggestionItems derived would call isVisible() which cascades
into model.getValueInRange() on the disposed model. Add an early return
guard to prevent this.

Fixes #318217

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 25, 2026 15:17
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@vs-code-engineering vs-code-engineering Bot requested review from Copilot and hediet May 25, 2026 15:18
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@vs-code-engineering vs-code-engineering Bot marked this pull request as ready for review May 25, 2026 15:18
@vs-code-engineering vs-code-engineering Bot enabled auto-merge (squash) May 25, 2026 15:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Error] unhandlederror-Model is disposed!

2 participants