ENOENT错误主因是./路径相对process.cwd()而非文件位置,导致路径解析不可控;应统一用path.join(__dirname, 'config.json')构建绝对路径,避免手动拼接、斜杠问题及跨平台兼容风险。

为什么 fs.readFile('./config.json') 总报 ENOENT?
不是 VSCode 的锅,是 Node.js 本身的行为:路径里的 ./ 指向的是终端当前工作目录(process.cwd()),而不是你正在运行的 JS 文件所在位置。你在项目根目录下执行 node src/app.js,./config.json 就会去根目录找;但如果你在 src/ 目录里执行 node app.js,它才去找 src/config.json——完全不可控。
常见现象:
- 在文件同级目录下运行成功,换到父目录或 VSCode 终端默认打开位置(通常是工作区根)就报
Error: ENOENT: no such file or directory, open './config.json' - VSCode 点击「在终端中打开」时,右键位置不同(点文件 vs 点文件夹 vs 空白处),
process.cwd()就不一样
怎么写路径才能稳住不崩?
必须用 __dirname + path.join() 锚定 JS 文件自身位置。这是 Node.js 官方推荐、跨平台安全的唯一靠谱做法。
实操要点:
- 别手动拼字符串,比如
__dirname + '/config.json'—— Windows 用\,Linux/macOS 用/,容易出错 - 必须引入
path模块:const path = require('path'); - 用
path.join(__dirname, 'config.json'),它自动处理斜杠方向、去重、规范化 - 读子目录或上级目录也一样:
path.join(__dirname, 'data', 'user.json')或path.join(__dirname, '..', '.env')
示例:
ZenHeart zenlink 与 zenlink-mcp 为 OpenClaw,涵盖安装、MCP 注册、钩子接线、入站轮询及升级维护。
const fs = require('fs');
const path = require('path');
const configPath = path.join(__dirname, 'config.json');
fs.readFile(configPath, 'utf8', (err, data) => {
if (err) throw err;
try {
const config = JSON.parse(data);
console.log(config.port);
} catch (e) {
throw new Error('JSON 解析失败:' + e.message);
}
});
JSON 文件内容非法,parse 就挂?
fs.readFile 只负责读取字符串,JSON.parse() 才真正解析。一旦 JSON 格式不对(比如末尾多逗号、单引号、注释、未转义换行),就会直接抛错,且错误堆栈指向 JSON.parse 行,容易误判成路径问题。
排查建议:
- 在 VSCode 中打开该 JSON 文件,右下角确认语言模式是
JSON(不是Plain Text或JSON with Comments) - 按
Ctrl+Shift+I尝试格式化——没反应?说明语法不合法;有反应但报错?看错误提示定位哪一行 - 临时改用
JSONC模式(支持//注释)调试,但上线前务必切回JSON并删掉所有注释 - 加
try/catch包住JSON.parse,避免整个进程崩溃
VSCode 终端启动位置到底在哪?
你以为你在对的地方,其实终端早就悄悄换了 cwd。最简单的验证方式,加两行调试输出:
console.log('当前工作目录:', process.cwd());
console.log('当前文件目录:', __dirname);
对比这两个值,立刻知道 ./xxx 去哪儿找了。VSCode 终端默认打开位置取决于你「右键 → 在集成终端中打开」时点击的位置——点一个 src/ 文件夹,process.cwd() 就是 src/;点空白处,就是工作区根目录。
复杂点在于:同一份代码,在不同人本地、CI 环境、甚至你自己不同终端 tab 里,process.cwd() 都可能不同。所以依赖 ./ 的路径写法,本质上就是埋雷。

















