You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
run this command in that folder mkdir .vscode && echo {"editor.fontSize": 33}>.vscode\settings.json
run the following node.js script in a terminal pointing to the folder vscode/.vscode
run this command in that folder rmdir /s /q .vscode\ && mkdir .vscode && echo {"editor.fontSize": 33}>.vscode\settings.json
constfs=require("fs");fs.watch("<path to a folder>/.vscode",(eventType,filename)=>{if(filename){console.log(`Event Type: ${eventType}`);console.log(`Filename: ${filename}`);}else{console.log("Filename not provided");}});
How often does it reproduce? Is there a required condition?
Always.
What is the expected behavior? Why is that the expected behavior?
After running the last command there should be change events reported in an endless fashion.
I've investigated this issue a bit. The root cause is not deleting and recreating the folder, but deleting it permanently (similar to Shift+Delete). When I tested deleting regularly (Delete from the File Explorer), I see this:
Event Type: change
Filename: settings.json
However, if I empty the recycle bin (permanent deletion), the same behavior is reached.
Regular deletion to the Recycle Bin is actually a move operation, which makes the original path invalid, thus the next ReadDirectoryChangesW call fails, and the watcher stops cleanly. Permanent deletion marks the directory for deletion, but since libuv holds an open handle, NTFS can't fully delete it yet. Instead, it moves the directory to $Extend$Deleted (a special NTFS holding area), and the handle remains valid, continuing to report events on this "zombie" path. This causes the infinite loop because ReadDirectoryChangesW keeps succeeding without errors.
I've tried a fix locally, and it worked, but I'll have to open a PR in libuv as that's where the root cause lies.
Reacted by Benjamin Pasero and justanotheranonymoususer
This issue has been marked as stale due to 90 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.
Still relevant — reproduced in the wild today (2026-07-29) on VS Code 1.130.0, Windows 11 10.0.26200, NTFS, no unusual filesystem drivers.
Two watcher utility processes (Code.exe --utility-sub-type=node.mojom.NodeService) were pegged at ~100% of a core each for 14 hours (~24% of an 8-core machine), having burned 13.9 CPU-hours apiece. Both held open handles under C:\$Extend\$Deleted\; the six idle sibling utility processes held zero — matching the signature described in microsoft/vscode#287800.
Native stack of the spinning thread confirms the loop is in libuv's fs-event path:
ntdll!NtQueryInformationFile
KERNELBASE!GetFileInformationByHandleEx
Code!uv_fs_event_stop+0x194 <- nearest exported symbol, not necessarily the actual frame
Code!uv_run
Time split on that thread was ~75% kernel / 25% user, consistent with a syscall retry loop rather than a JS-side spin. No memory or handle growth over the 14 hours — pure spin, and no file in either watched tree had changed for hours.
This also lines up with @StefanStojanovic's analysis above: both affected workspaces had a watched directory permanently deleted (not sent to the Recycle Bin), leaving the zombie handle behind.
Noting for the stale bot: the fix is reported above as landed in libuv on 2026-03-31, but libuv's latest release (v1.52.1) is dated 2026-03-06 — it predates the fix, so it hasn't been able to flow into Node/Electron/VS Code yet. Still reproducing on current VS Code as of today.
Activity
justanotheranonymoususer commentedon Jan 16, 2026
I also wrote some observations here: microsoft/vscode#263718 (comment)
Actual
ReadDirectoryChangesWcall is in libuv, so might also be a libuv bug.StefanStojanovic commentedon Jan 29, 2026
I've investigated this issue a bit. The root cause is not deleting and recreating the folder, but deleting it permanently (similar to Shift+Delete). When I tested deleting regularly (Delete from the File Explorer), I see this:
However, if I empty the recycle bin (permanent deletion), the same behavior is reached.
Regular deletion to the Recycle Bin is actually a move operation, which makes the original path invalid, thus the next
ReadDirectoryChangesWcall fails, and the watcher stops cleanly. Permanent deletion marks the directory for deletion, but since libuv holds an open handle, NTFS can't fully delete it yet. Instead, it moves the directory to $Extend$Deleted (a special NTFS holding area), and the handle remains valid, continuing to report events on this "zombie" path. This causes the infinite loop becauseReadDirectoryChangesWkeeps succeeding without errors.I've tried a fix locally, and it worked, but I'll have to open a PR in libuv as that's where the root cause lies.
win: fix watch loop logic
win: fix watch loop logic
win: fix watch loop logic (#5013)
StefanStojanovic commentedon Mar 31, 2026
The fix for this has landed in the libuv project. The next time libuv is released and pulled into Node.js, this issue will be resolved.
Squashed commit of the following:
Migrate file watchers from fs.watch to VS Code FileSystemWatcher API
Migrate file watchers from fs.watch to VS Code FileSystemWatcher API
Migrate file watchers from fs.watch to VS Code FileSystemWatcher API
Migrate file watchers from fs.watch to VS Code FileSystemWatcher API
Migrate file watchers from fs.watch to VS Code FileSystemWatcher API
Migrate file watchers from fs.watch to VS Code FileSystemWatcher API
Migrate file watchers from fs.watch to VS Code FileSystemWatcher API
Migrate file watchers from fs.watch to VS Code FileSystemWatcher API
Migrate file watchers from fs.watch to VS Code FileSystemWatcher API
Migrate file watchers from fs.watch to VS Code FileSystemWatcher API
github-actions commentedon Jul 20, 2026
This issue has been marked as stale due to 90 days of inactivity.
It will be automatically closed in 30 days if no further activity occurs. If this is still relevant, please leave a comment or update it to keep it open.
relmer commentedon Jul 29, 2026
Still relevant — reproduced in the wild today (2026-07-29) on VS Code 1.130.0, Windows 11 10.0.26200, NTFS, no unusual filesystem drivers.
Two watcher utility processes (
Code.exe --utility-sub-type=node.mojom.NodeService) were pegged at ~100% of a core each for 14 hours (~24% of an 8-core machine), having burned 13.9 CPU-hours apiece. Both held open handles underC:\$Extend\$Deleted\; the six idle sibling utility processes held zero — matching the signature described in microsoft/vscode#287800.Native stack of the spinning thread confirms the loop is in libuv's fs-event path:
Time split on that thread was ~75% kernel / 25% user, consistent with a syscall retry loop rather than a JS-side spin. No memory or handle growth over the 14 hours — pure spin, and no file in either watched tree had changed for hours.
This also lines up with @StefanStojanovic's analysis above: both affected workspaces had a watched directory permanently deleted (not sent to the Recycle Bin), leaving the zombie handle behind.
Noting for the stale bot: the fix is reported above as landed in libuv on 2026-03-31, but libuv's latest release (v1.52.1) is dated 2026-03-06 — it predates the fix, so it hasn't been able to flow into Node/Electron/VS Code yet. Still reproducing on current VS Code as of today.