VS Code version: Version: 1.125.1 (user setup)
Commit: fcf6047
Date: 2026-06-19T08:39:34Z
Electron: 42.2.0
ElectronBuildId: 14159160
Chromium: 148.0.7778.97
Node.js: 24.15.0
V8: 14.8.178.14-electron.0
OS: Windows_NT x64 10.0.26100
Extension: built-in copilot extension (resources/app/extensions/copilot/dist/extension.js)
Summary
During workspace startup, the extension-host main thread is frozen for ~14 seconds inside a single synchronous require() triggered by the built-in Copilot extension's first HTTPS request. Because the entire extension host shares one JS thread, this blocks all other extensions' timers, microtasks, and I/O callbacks for the duration. In my case it delayed the Pylance language client from sending its initialize request to the (already-spawned) language server by ~14–60s, making the language server appear to "hang" at startup.
Root cause
When Copilot opens its first HTTPS connection, the TLS handshake completes and undici lazily require()s its HTTP/1 parser (llhttp) from inside the connection callback. That require is a synchronous CommonJS module load (readFileSync → readFileUtf8). On Windows the read appears to be heavily amplified by Defender real-time scanning and disk contention from other extensions spawning child processes at startup, stretching this one synchronous load to ~14s.
A synchronous require cannot yield, so for those ~14s the event loop runs zero timers/microtasks/I-O callbacks — every other extension and any language client running in the host is starved.
Evidence (CPU profile)
The startup window (0–35s) is ~95% CPU-saturated (33.4s busy / 35s). Within it there is a single contiguous 13.9s run (+7.8s → +21.7s) where readFileSync/readFileUtf8 is the leaf on the stack, and 100% of the samples in that run (8315/8315) root to the copilot extension. Representative stack (leaf → root):
readFileUtf8 [native]
readFileSync [node:fs]
t.readFileSync [node:electron/js2c/node_init]
defaultLoadImpl / loadSource [node:internal/modules/cjs/loader]
Module._extensions..js / Module.load [node:internal/modules/cjs/loader]
Module._load / wrapModuleLoad [node:internal/modules/cjs/loader]
Module.require [node:internal/modules/cjs/loader]
require [resources/app/extensions/copilot/dist/extension.js]
lazyllhttp [node_modules/undici/lib/dispatcher/client-h1.js]
connectH1 [node_modules/undici/lib/dispatcher/client-h1.js]
onConnectSecure [node:internal/tls/wrap]
TLSSocket._finishInit [node:internal/tls/wrap]
ssl.onhandshakedone [node:internal/tls/wrap]
(root)
During this whole window the affected language client received only ~0.6s of CPU — i.e. it was effectively frozen, not doing async work of its own.
Impact
- Any extension or language client sharing the extension host stalls for the duration of the synchronous load.
- Symptom observed: a language server that has already spawned sits idle for up to ~60s before receiving
initialize, looking like a hang.
- Worse on Windows due to Defender scanning + concurrent child-process disk contention at startup.
Suggested mitigations
- Pre-warm undici's
llhttp asynchronously (or eagerly import() it) before/at activation, off the hot connection path, so the first HTTPS request doesn't trigger a synchronous module load on the shared thread.
- Avoid issuing the first network request synchronously during the busiest part of startup, or defer it until after the host has settled.
- (Upstream) consider an async
llhttp load path in undici so connectH1 doesn't require() synchronously inside the TLS callback.
Workaround for users
Adding a Microsoft Defender exclusion for the VS Code install directory noticeably reduces the synchronous read time.
VS Code version: Version: 1.125.1 (user setup)
Commit: fcf6047
Date: 2026-06-19T08:39:34Z
Electron: 42.2.0
ElectronBuildId: 14159160
Chromium: 148.0.7778.97
Node.js: 24.15.0
V8: 14.8.178.14-electron.0
OS: Windows_NT x64 10.0.26100
Extension: built-in
copilotextension (resources/app/extensions/copilot/dist/extension.js)Summary
During workspace startup, the extension-host main thread is frozen for ~14 seconds inside a single synchronous
require()triggered by the built-in Copilot extension's first HTTPS request. Because the entire extension host shares one JS thread, this blocks all other extensions' timers, microtasks, and I/O callbacks for the duration. In my case it delayed the Pylance language client from sending itsinitializerequest to the (already-spawned) language server by ~14–60s, making the language server appear to "hang" at startup.Root cause
When Copilot opens its first HTTPS connection, the TLS handshake completes and
undicilazilyrequire()s its HTTP/1 parser (llhttp) from inside the connection callback. Thatrequireis a synchronous CommonJS module load (readFileSync→readFileUtf8). On Windows the read appears to be heavily amplified by Defender real-time scanning and disk contention from other extensions spawning child processes at startup, stretching this one synchronous load to ~14s.A synchronous
requirecannot yield, so for those ~14s the event loop runs zero timers/microtasks/I-O callbacks — every other extension and any language client running in the host is starved.Evidence (CPU profile)
The startup window (0–35s) is ~95% CPU-saturated (33.4s busy / 35s). Within it there is a single contiguous 13.9s run (+7.8s → +21.7s) where
readFileSync/readFileUtf8is the leaf on the stack, and 100% of the samples in that run (8315/8315) root to thecopilotextension. Representative stack (leaf → root):During this whole window the affected language client received only ~0.6s of CPU — i.e. it was effectively frozen, not doing async work of its own.
Impact
initialize, looking like a hang.Suggested mitigations
llhttpasynchronously (or eagerlyimport()it) before/at activation, off the hot connection path, so the first HTTPS request doesn't trigger a synchronous module load on the shared thread.llhttpload path inundicisoconnectH1doesn'trequire()synchronously inside the TLS callback.Workaround for users
Adding a Microsoft Defender exclusion for the VS Code install directory noticeably reduces the synchronous read time.