VS Code Node.js的“launch”断点在Windows上不生效(attach调试可用)——取决于Node版本
在Windows上,我的VS Code启动调试配置突然无法命中断点。断点显示为“Unbound breakpoint”(未绑定的断点),一个 debugger; 语句被忽略,程序运行到完成并退出,退出码为0,console.log 的输出有时甚至都没有出现。调试控制台中没有任何错误。
奇怪的地方是:attach 能正常工作(手动运行 node --inspect 并附加时能绑定断点)——只有 launch 出问题。完全相同的项目/配置在同事的机器上也能正常工作。
最小可重现步骤 - index.js:
debugger;
console.log('hello');
.vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{ "name": "Launch Program", "type": "node", "request": "launch", "program": "${workspaceFolder}/index.js" }
]
}
按F5 → 没有任何断点被触发,进程就直接退出。Node是通过nvm-windows安装的。
是什么原因造成的,且在不修改共享的 launch.json 的情况下,如何修复?
解决方案
Root cause:Node.js在 Windows上的一个回归问题,而不是VS Code的问题。
VS Code的 JavaScript调试器(js-debug)通过 NODE_OPTIONS=--require <bootloader> 向启动的进程注入一个引导加载程序。在打开调试器前,引导加载程序通过列出管道目录来验证调试IPC命名管道是否处于活动状态:
// simplified from the js-debug bootloader
fs.readdirSync(path.dirname(inspectorIpc)).includes(path.basename(inspectorIpc))
// path.dirname("\\.\pipe\node-cdp...") === "\\.\pipe\"
在受影响的Node版本上,fs.readdirSync('\\\\.\\pipe\\') 在Windows上抛出 ENOTDIR。该检查返回false,引导加载程序会悄悄地禁用自身——不会打开调试器、不会建立CDP连接,断点也永远不会绑定。attach 能工作,因为它直接连接到 --inspect 端口,从不执行此检查。
要检查你的Node版本是否受影响,请使用你调试时所使用的Node来运行它:
const fs = require('fs');
try { fs.readdirSync('\\\\.\\pipe\\'); console.log('OK — launch debugging works'); }
catch (e) { console.log('BROKEN —', e.code, '— launch breakpoints are disabled'); }
修复:切换到具有 fs.readdir 命名管道修复的Node版本。
| Node版本线 | 已损坏 | 已修复 |
|---|---|---|
| 20.x | 20.20.0及以后 | 20.19.x及以前 |
| 22.x | 22.13.0之前 | 22.13.0及以上 |
| 23.x | 23.2.0 – 23.4.x | 23.5.0及以上 |
| 24.x | — | all* |
该回归首次出现在Node 23.2.0,并已回溯到20.x/22.x系列;修复(nodejs/node#56110)在v22.13.0和 v23.5.0中发布。
在nvm-windows下:
nvm install 22.13.0
nvm use 22.13.0
....然后按F5。无需对 launch.json 做出任何修改。
* 如果你在非常新的24.x/22.x版本上仍然看到该症状,请运行上面的片段 — 有更新但尚未证实的报道(nodejs/node#60194)。
参考资料