必须开启autoattachchildprocesses,否则worker和fork子进程无法进入vs code调试器;该配置是硬性前提,需在launch.json中显式设置为true,并配合--inspect-brk参数、正确端口及路径,且断点命中后需手动切换线程上下文。

必须开启 autoAttachChildProcesses,否则 Worker 和 fork 子进程根本进不了调试器
VS Code 默认只调试主线程,autoAttachChildProcesses: true 是唯一能让调试器“看见” Worker Threads 或 child_process.fork() 子进程的开关。它不是锦上添花,而是硬性前提——没它,断点在 worker.js 里永远是空心圆,console.log 可能直接被吞掉。
这个配置只对两类创建方式生效:new Worker() 和 fork();spawn() 不会自动识别,除非你手动加 --inspect 参数。
-
launch.json中必须显式写"autoAttachChildProcesses": true,不能只靠"runtimeArgs": ["--inspect"] - 如果用了
ts-node、esbuild-node等非标准启动器,autoAttachChildProcesses会失效——它们绕过了 Node.js 原生调试协议 - macOS/Linux 下用 nvm 管理 Node 版本时,必须在
launch.json中指定"runtimeExecutable",否则子进程可能调用错版本
Worker 启动必须带 --inspect-brk,且端口要匹配
Node.js 的 Worker 默认不暴露调试端口,即使开了 autoAttachChildProcesses,也会跳过附加——因为没端口可连。
正确做法是在构造时传入调试参数:
new Worker('./worker.js', { execArgv: ['--inspect-brk=9229'] });
同时确保 launch.json 中对应配置一致:
-
"runtimeArgs": ["--inspect-brk"](主进程监听) -
"port": 9229(必须与execArgv中端口号完全一致) - 端口不能被占用;多个 Worker 实例共用同一端口会导致只连上第一个——要么用唯一端口,要么干脆不指定端口让 Node 自动分配
fork() 子进程调试失败?大概率漏了 execArgv
常见错误写法:fork('./sub.js') —— 这个子进程完全不知道自己该被调试,VS Code 根本收不到它的调试握手请求。
ZenHeart zenlink 与 zenlink-mcp 为 OpenClaw,涵盖安装、MCP 注册、钩子接线、入站轮询及升级维护。
正确写法必须显式传递调试参数:
fork('./sub.js', [], { execArgv: ['--inspect=9230'] });
注意几点:
- 端口号建议和主线程错开(比如主线程用 9229,子进程用 9230),避免冲突
- 路径必须是相对
__dirname或绝对路径,避免受process.cwd()影响 - 如果子进程启动极快(如纯计算型),可在入口加
parentPort?.postMessage('ready'),主线程监听确认加载完成再继续,防止断点错过
断点命中后看不到变量?得手动切线程上下文
VS Code 不支持自动跨线程同步变量面板,断点触发后,调试焦点默认还在 Main Thread,你得主动切换。
操作步骤很直接:
- 断点停住后,先看右上角线程下拉框——里面应有
Main Thread和类似Worker Thread #1的条目 - 快捷键
Ctrl+Shift+P→ 输入Debug: Switch Thread→ 回车 → 选目标线程(比手动点下拉更可靠) - 切换后,调用栈、变量、监视表达式才会更新为当前线程上下文
容易被忽略的是:如果 worker.js 路径解析错误、或被 .gitignore / files.exclude 隐藏,断点会绑定失败,现象仍是空心圆——这不是线程问题,是源码定位失败,得检查路径和 workspace 设置。










