Skip to content

fix(workflow-lsp): prevent uncaught 'Connection is disposed' during teardown#2385

Merged
curtisman merged 1 commit into
microsoft:mainfrom
curtisman:fix-workflow-lsp-dispose-race
May 22, 2026
Merged

fix(workflow-lsp): prevent uncaught 'Connection is disposed' during teardown#2385
curtisman merged 1 commit into
microsoft:mainfrom
curtisman:fix-workflow-lsp-dispose-race

Conversation

@curtisman
Copy link
Copy Markdown
Member

Problem

Intermittent CI failure in examples/workflow/lsp tests:

ConnectionError: Connection is disposed.
    at throwIfClosedOrDisposed (vscode-jsonrpc/lib/common/connection.js:832:19)
    at Object.sendNotification (vscode-jsonrpc/lib/common/connection.js:910:13)
    at RemoteConsoleImpl.send (vscode-languageserver/lib/common/server.js:104:33)
    at RemoteConsoleImpl.error (vscode-languageserver/lib/common/server.js:88:14)
    at vscode-jsonrpc/lib/common/connection.js:951:24

Root cause

When the underlying transport is destroyed (common during jest teardown), vscode-jsonrpc's pending messageWriter.write(...) promise rejects. Its internal .catch calls logger.error(...). That logger is the server's connection.console (a RemoteConsoleImpl), whose send() invokes connection.sendNotification(...), which throws synchronously via throwIfClosedOrDisposed() once the connection is disposed. The synchronous throw escapes the internal .catch and surfaces as an uncaught exception that crashes the worker.

Fix

In server.dispose(), replace connection.console.{error,warn,info,log,debug} with no-ops before calling connection.dispose(). Any post-dispose log attempts from the jsonrpc layer now no-op instead of throwing.

Validation

Built and ran the LSP test suite 5 times in a row locally; all 121 tests pass on each run with no uncaught exceptions.

…eardown

When the underlying transport is destroyed (common in jest tests),
vscode-jsonrpc's pending messageWriter.write rejects and its .catch
calls logger.error(...). The logger is the server's connection.console,
whose send() invokes connection.sendNotification, which throws
synchronously via throwIfClosedOrDisposed once the connection is
disposed. That synchronous throw escapes the internal .catch and
surfaces as an uncaught exception that crashes the worker.

Neutralize connection.console in server.dispose() before disposing the
connection so any post-dispose log attempts no-op instead of throwing.
@curtisman curtisman requested a deployment to development-fork May 22, 2026 22:51 — with GitHub Actions Waiting
@curtisman curtisman requested a deployment to development-fork May 22, 2026 22:51 — with GitHub Actions Waiting
@curtisman curtisman enabled auto-merge May 22, 2026 22:51
@curtisman curtisman added this pull request to the merge queue May 22, 2026
Merged via the queue into microsoft:main with commit 4c79d12 May 22, 2026
13 of 15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant