sessions: defer managed Changes tab reconciliation until working-set restore settles - #332123
Open
Alexandru Dima (alexdima) wants to merge 2 commits into
Open
sessions: defer managed Changes tab reconciliation until working-set restore settles#332123Alexandru Dima (alexdima) wants to merge 2 commits into
Alexandru Dima (alexdima) wants to merge 2 commits into
Conversation
Avoid replacing the active Changes tab while an asynchronous session working-set restore is still replacing the editor group. Keep the latest reconcile intent pending so the existing restore-end trigger applies it against the settled group. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Alexandru Dima (alexdima)
requested review from
Sandeep Somavarapu (sandy081)
and
a balanced review from Copilot
August 22, 2026 14:35
Contributor
📬 CODENOTIFYThe following users are being notified based on files changed in this PR: Benjamin Christopher Simmonds (@benibenj)Matched files:
|
Contributor
There was a problem hiding this comment.
Pull request overview
Defers managed-tab reconciliation until session working-set restoration settles, preventing editor replacement races.
Changes:
- Preserve pending reconciliation intent during restores.
- Reconcile after restore completion.
- Add regression coverage for session switching.
Show a summary per file
| File | Description |
|---|---|
singlePaneDockedTabsCoordinator.ts |
Defers reconciliation during layout restoration. |
desktopSessionLayoutController.test.ts |
Tests deferred Changes-tab replacement. |
Review details
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Balanced
Exercise the restore guard inside the sequencer callback by queueing a stale Changes replacement before a gated restore begins. Verify that replacement remains pending until the restore-end reconciliation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I generated this by scanning my logs, pls take if it's good/useful
🤖
Summary
Defer the single-pane managed Changes/Files tab reconciliation while a session working-set restore is in progress, then let the existing restore-end reconciliation apply the latest accumulated intent against the settled editor group.
This prevents the managed-tab coordinator from replacing a stale Changes tab concurrently with
IEditorGroupsService.applyWorkingSet, which can dispose and recreate the editor group underneath that replacement.User-visible symptom and log evidence
While switching rapidly among recent Agent Host sessions in the Agents Window, the renderer repeatedly logged a canceled editor open immediately followed by a disposed scoped instantiation service:
I found 10 occurrences of
InstantiationService has been disposedacross recent Insiders sessions on August 19-21, all with the same managed-tab reconciliation path.The second error is a consequence of the first: once the editor open is canceled, the editor pane attempts to show an error placeholder, but the old editor group's scoped instantiation service has already been disposed by the concurrent working-set replacement.
Root cause
A session switch currently drives two related asynchronous paths:
BaseLayoutControllerapplies the incoming session's editor working set under_withSessionLayoutRestore(...).SinglePaneDockedTabsCoordinatorobserves the active-session change and immediately queues an ambient managed-tab reconciliation.The coordinator's
_reconcileForeignChangesEditorscan therefore callgroup.replaceEditors(...)for the incoming session's Changes tab whileapplyWorkingSet(...)is still replacing the outgoing editor group. The coordinator holds the group captured before the asynchronous operation settles, so its replacement can continue against a group whose scoped services have since been disposed.The controller already exposes the intended synchronization boundary:
ctx.isRestoringSessionLayoutis true for the full asynchronous restore.ctx.onDidEndSessionLayoutRestorequeues a reconciliation after the restore depth returns to zero.The ambient session-change path was not respecting that boundary.
Fix
queueReconcilestill records the latest target, merges triggers for the same session, and advances the generation while restoration is active, but it does not start work against the transient editor group._reconcilealso checksisRestoringSessionLayoutbefore consuming_pending. This covers work that was queued immediately before a restore began but had not started yet.When restoration settles, the existing
onDidEndSessionLayoutRestorelistener queues the final reconciliation. Because_pendingwas retained rather than discarded, trigger intent is preserved and merged with the restore-end trigger, while the newest generation continues to supersede stale queued work.This is intentionally not an exception filter and does not suppress
Canceledor disposed-service errors. It removes the ordering race that causes them.Regression coverage
The tests cover both sides of the scheduling boundary:
queueReconcileretains the intent without scheduling replacement, then applies it after restore end._reconcileguard leaves the old tab untouched during restore and that the restore-end reconciliation performs exactly one replacement for the active session.Together they verify that:
replaceEditorscall occurs against a transient editor group;Validation
npm run transpile-client./scripts/test.sh --run src/vs/sessions/contrib/layout/test/browser/desktopSessionLayoutController.test.tsgit diff --checkReviewer context
Sandeep Somavarapu (@sandy081), this touches the generation/pending-intent logic introduced as part of the recent single-pane lifecycle stabilization work. The key behavior to review is that pending intents remain accumulated during restore and are consumed only by the already-existing restore-end reconciliation, rather than being dropped or run against the outgoing group.