在PowerShell里敲下 npm install 回车,等了半天,屏幕上却没有按预期开始刷依赖列表,而是弹出一段红字,里面同时出现了 D:\openclaw\node_modules\npm\bin\npm-cli.js 和 CategoryInfo : NotSpecified: (npm error co... 两行看起来完全不像普通报错的东西。我第一次遇到的时候也懵了:npm 不是在运行吗?怎么还报一个找不到类别的错误?
后来才搞清楚,这个问题根本不是 npm 本体坏了,而是 Windows 的 PowerShell 压根没允许 npm 的脚本启动。对于准备在 Windows 上部署 OpenClaw 的朋友来说,这基本是绕不过去的第一个坎。OpenClaw 这类智能体项目,不管你想接微信、飞书还是钉钉,第一步大概率都是 npm install,所以把这条链路彻底弄明白,后面能省掉很多折腾时间。这篇文章就用我实际踩坑的视角,把 Windows 上 npm 启动失败、node_modules 异常、OpenClaw 启动后连不上模型等问题完整捋一遍,每个问题都会给到可以直接抄的解决方案。
1. 从报错现场出发:npm-cli.js、CategoryInfo 和 PowerShell 到底拦住了什么
1.1 报错信息在说什么
先拆第一段报错,路径是 D:\openclaw\node_modules\npm\bin\npm-cli.js。很多人看到这个路径会以为 npm 找不到自己了,实际上它是在告诉你:npm 其实是一个 Node.js 脚本,真正的入口就是这个 npm-cli.js。在 Windows 上,npm 安装时会生成几个启动器,比如 npm.cmd、npm.ps1,它们的作用就是用 Node 去执行这个 npm-cli.js。所以当你在 PowerShell 里输入 npm 时,PowerShell 其实是在尝试调用 npm.ps1 这个脚本,再由它去拉起 Node 和 npm-cli.js。
再拆第二段,CategoryInfo : NotSpecified: (npm error co...。这个格式不是 npm 输出的,而是 PowerShell 在把原生程序输出包装成错误记录时统一加的壳。CategoryInfo 是 PowerShell 错误记录的一个属性,NotSpecified 表示它无法把这条错误归类到某个具体的 .NET 异常类型里。也就是说,这一行只是“外壳”,真正的错误原因在后面的 npm error co... 里。如果你只盯着这个 CategoryInfo 看,会浪费很多时间。真正要关注的,是它前面那条更经典的报错:“无法加载文件 ...\npm.ps1,因为在此系统上禁止运行脚本”。
也就是说,这条报错链的完整逻辑是:PowerShell 想执行 npm.ps1,但被 Windows 的执行策略拦住了,于是它没能正常启动 npm-cli.js,所有后续输出都被 PowerShell 包成了一个 CategoryInfo : NotSpecified 的错误记录。问题根源在 PowerShell 的执行策略,而不是 npm 被删了或者 Node.js 坏了。
1.2 为什么 PowerShell 会禁止运行脚本
Windows 的 PowerShell 有一套执行策略(Execution Policy),它控制着 .ps1 脚本能不能运行。默认策略在不同系统上不完全一样,但很多 Windows 机器默认是 Restricted,也就是禁止运行任何 .ps1 脚本。npm 在 Windows 上偏偏主要依赖 npm.ps1 作为启动器,于是整个 npm 就被“一刀切”拦住了。
你可以把执行策略理解成小区门口的保安。保安的职责不是判断访客是好是坏,而是看这个访客有没有“出入证”。npm.ps1 是一个本地生成的脚本文件,没有任何签名,默认规则下属于“没有许可证的陌生人”,所以直接被拒绝进入。问题在于,这个“门禁规则”平时开发时几乎不会用到,一旦项目需要跑 npm 命令,就被卡住了。
PowerShell 的执行策略其实分多个作用域,可以用 Get-ExecutionPolicy -List 查看。常见策略值和作用如下:
| 策略值 | 含义 | 适用场景 |
|---|---|---|
| Restricted | 禁止运行任何 .ps1 脚本 | Windows 默认策略,安全性最高,但不适合日常开发 |
| RemoteSigned | 本地脚本可运行,远程下载脚本必须签名 | 开发机推荐,兼顾安全与便利 |
| AllSigned | 所有脚本都必须签名 | 企业管控严格的环境 |
| Unrestricted | 运行所有脚本,但运行时提示 | 不推荐,安全性较低 |
| Bypass | 完全不检查,运行所有脚本 | 临时命令、自动化部署场景 |
看到这里你应该明白,最典型的修复方式就是把执行策略改成 RemoteSigned,让本地生成的 npm.ps1 这类脚本能正常跑,同时又不会乱放行网上下载的未签名脚本。这里提醒一下,如果发现改完当前用户策略还是不行,记得检查是不是有组策略(MachinePolicy 或 UserPolicy)覆盖了你的设置。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 五分钟修复:让 npm 在 Windows 终端里恢复正常执行的三种方式
2.1 方案一:修改 PowerShell 执行策略,一劳永逸
这是最推荐的方案,因为不管是 VSCode 的终端、Windows Terminal 还是系统自带的 PowerShell,默认都受这套策略管控。改完之后,所有终端里的 npm 命令都会恢复正常。
先打开 PowerShell,注意如果你当前的用户是管理员,可以直接以管理员身份打开。然后执行:
powershell复制Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
如果当前用户没有权限,也可以用管理员 PowerShell 执行:
powershell复制Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
执行后终端会询问是否确认,输入 Y 回车即可。然后验证一下:
powershell复制Get-ExecutionPolicy -List
看到 CurrentUser 或 LocalMachine 对应的值是 RemoteSigned,就说明修改成功了。这时建议关掉当前终端,重新打开一个新的 PowerShell 窗口,再试:
powershell复制npm -v
实测下来,这一步能解决绝大多数“无法加载文件 npm.ps1,因为在此系统上禁止运行脚本”的报错。这里有一个细节:-Scope CurrentUser 只对当前用户生效,不需要管理员权限,也别怕影响系统其他用户,这是最安全的做法。很多教程一上来就让管理员开全局,其实没必要。
2.2 方案二:不碰执行策略,用 cmd 或 Git Bash 绕过
如果你在公司的电脑上,没有管理员权限,或者出于安全考虑不想修改执行策略,那就换个壳。npm 的问题只在 PowerShell 里存在,因为在 PowerShell 中 npm 会优先找 npm.ps1。而 cmd 不会检查 .ps1 脚本,它直接执行 npm.cmd,所以完全没有这个限制。
最简单的临时办法是在 PowerShell 里输入:
powershell复制cmd /c npm install
或者直接打开命令提示符(cmd),在里面运行 npm 命令。如果你装了 Git 的话,Git Bash 也可以。这种方式对临时跑一条命令非常方便,但缺点也很明显:你没法在 PowerShell 里顺畅地执行所有 npm 相关操作,比如 npm run dev 后想 Ctrl+C 中断,在 cmd 会话里的体验会差一些。
还有一个小技巧:PowerShell 里如果不想改策略,又想在当前窗口继续用 npm,可以用 powershell -ExecutionPolicy Bypass 启动一个绕过策略的子会话:
powershell复制powershell -ExecutionPolicy Bypass -Command "npm install"
这在执行固定命令时比较实用,但每次都要敲一长串,适合应急,不适合作为日常方案。
2.3 方案三:用 nvm 或重装 Node.js 时顺带修复环境变量
有一种特殊情况:你的 npm 命令报错,不是脚本被拦截,而是干脆输出“npm 不是内部或外部命令”。这种情况和执行策略无关,是 Node.js 的 bin 目录不在 PATH 环境变量里。特别是用 nvm-windows 管理 Node 版本时,如果版本切换失败,或者 Node 目录被移动过,就会出现这种问题。
检查方法很简单:
bash复制node -v
npm -v
如果 node -v 正常,但 npm -v 提示找不到命令,大概率是 npm 所在的目录不在 PATH 里。用 nvm-windows 的话,可以重新执行 nvm list,看看当前版本是否生效,然后 nvm use 20 切换到具体版本。如果手头没有 nvm,直接卸载 Node.js,重新安装时注意勾选 “Add to PATH” 选项,一般就能解决。
这里给个建议:OpenClaw 这类项目对 Node 版本有要求,不建议直接用最新的大版本。我实测下来,Node 18 和 20 的 LTS 版本兼容性最稳,如果你用的是 21 以上版本,碰到某些依赖编译不过,大概率是版本太新导致的。用 nvm-windows 管理多个版本,方便随时切换。
3. 装 OpenClaw 时真正容易踩的坑:node_modules、镜像源和模型配置
3.1 配置 npm 镜像源,安装速度翻倍
执行策略修好之后,很多人以为马上就能顺利 npm install 了,结果发现 OpenClaw 的依赖树非常庞大,在默认源下安装速度慢得离谱,甚至直接卡在某个包上下载超时。这个问题在 Windows 上尤其明显,因为很多包还需要下载二进制文件,网络往返次数一多,失败概率就上来了。
解决办法是配置 npm 镜像源。常见的做法是把 npm registry 切到国内镜像,这样依赖下载速度会快很多。
bash复制npm config set registry https://registry.npmmirror.com
配置完可以用下面命令验证是否生效:
bash复制npm config get registry
看到返回的是 https://registry.npmmirror.com/ 就说明切换成功了。如果后续想恢复官方源,执行 npm config delete registry 即可。
这里补充一个排查点:很多时候卡在安装阶段,不一定是源的问题,而是安装过程被中断后没有清理干净。如果你已经在项目目录下执行过 npm install,结果中途 Ctrl+C 或者电脑断电了,接下来再执行 install 可能会报各种奇怪的错。这时候不要犹豫,直接把 node_modules 删掉重装:
bash复制rm -rf node_modules package-lock.json
npm install
如果你希望严格按 package-lock.json 里的依赖树安装,可以用:
bash复制npm ci
npm ci 和 npm install 的区别在于,它会严格依据 package-lock.json 进行完整干净的安装,不会随意升级依赖,而且安装前会先自动清空 node_modules。对 OpenClaw 这种对依赖版本比较敏感的项目,用 npm ci 比 npm install 靠谱得多。
3.2 node_modules 里那些带下划线(_)的目录,千万别手动改
关于 node_modules 里的下划线目录,我见过太多人在里面栽跟头了。尤其是有内网开发习惯的人,喜欢把整个 node_modules 压缩打包传给同事解压使用。解压之后打开目录,发现里面一堆依赖名称带下划线前缀,比如 _vue、_@types+node 之类的东西。更尴尬的是,打开项目执行 npm run dev 直接报错,于是开始怀疑是不是压缩包损坏了。
实际上,这些带下划线的目录是包管理器在解析依赖树时产生的内部结构。npm 在安装依赖时,如果遇到包名冲突、嵌套依赖需要提升、或者某些 scoped 依赖的特殊处理,会在 node_modules 下生成下划线开头的临时目录。它属于包管理器的“内部工地”,不是项目代码的一部分。
正确的处理方式是:不要手动去重命名或删除这些目录,也不要直接复制别人机器上的 node_modules 到自己的项目里。npm 官方也从来不建议跨平台、跨机器直接拷贝 node_modules。因为很多包在安装时会根据当前系统生成对应的二进制文件或符号链接,Windows 上正常的东西,拷到另一台 Windows 机器都可能出问题,更别说跨平台了。
如果你已经踩了这个坑,最简单的解决办法是删掉这些目录,重新执行安装:
bash复制rm -rf node_modules
npm ci
这样会重新生成一份与当前系统匹配的依赖树。以后要传递项目代码,只传 package.json 和 package-lock.json 就够了,然后让目标机器重新执行 npm ci。这样虽然多花一点下载时间,但能避免大量诡异问题。
这里再提一个小建议:尽量不要用 npm install --force 来硬装依赖。很多人在依赖冲突时习惯加 --force,虽然能装上,但 npm 会提示 npm warn using --force recommended protections disabled,意思是强制模式关闭了默认的保护机制。依赖树可能装出一个脏环境。遇到 peerDependencies 冲突时,优先尝试 npm install --legacy-peer-deps,这个参数是专门处理旧版依赖树冲突的,比 --force 温和得多,OpenClaw 这类项目里实测可用。
3.3 装完之后别急着跑,先检查 Node 版本和模型配置
OpenClaw 安装完依赖后,启动时报错也是高频问题。热词里有个典型报错:“OpenClaw 0.1.7 node runtime not found”。这个报错的含义很直接:OpenClaw 找不到 Node.js 运行环境。但你明明刚用 node -v 验证过 Node 存在,这时候就要怀疑是不是 nvm 切换了版本之后 OpenClaw 缓存了旧路径,或者系统 PATH 里 Node 目录没有排在第一位。
我遇到过的场景是:用 nvm-windows 同时装了 Node 18 和 Node 22,OpenClaw 是用 Node 18 安装的,后来切到 Node 22 后再启动,就报 runtime not found。解决办法也比较简单:先 nvm use 18 切回原来安装时用的 Node 版本,重新启动 OpenClaw,如果还是不行,就把 Node 重装一遍,安装时勾选 Add to PATH。再不行就检查 Windows 的环境变量窗口,确认包含 D:\nodejs 或对应 nvm 路径的条目排在最前面。
另一个典型坑是模型配置错误。热词里就有“OpenClaw 0.3.0 zero token 安装后 agent failed before reply: unknown model: deepseek”这种情况。意思很简单:配置里填的模型名不对,OpenClaw 不认。你以为是填“DeepSeek”还是“deepseek-chat”的问题,其实完全取决于你用的 API 服务商的模型标识。比如 DeepSeek 的模型 ID 可能是 deepseek-chat,而你在配置里写成了 deepseek,就会报 unknown model。解决方法是去对应模型平台的 API 文档里查准确的 model id,而不是凭感觉填名称。这个细节在接本地模型或者第三方兼容 API 时尤其重要,同一个模型在不同平台上的 ID 可能完全不同。
4. 高频报错排查清单与我的实践笔记
4.1 一条完整的排障路径,按顺序执行不迷路
把前面所有问题串起来,当你再次遇到 OpenClaw 在 Windows 上装不出来时,建议按照以下顺序排查。这就像一个固定的体检流程,按顺序走一遍,大多数问题都能定位到。
第一步,先看 Node 和 npm 是否可用。打开 PowerShell,分别执行:
powershell复制node -v
npm -v
如果 node -v 有输出但 npm -v 报错,优先检查 PATH 和执行策略。这一步能过滤掉最基础的环境问题。
第二步,确认执行策略状态:
powershell复制Get-ExecutionPolicy -List
如果看到 Restricted,执行 Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser 修复。
第三步,检查 npm 镜像源:
powershell复制npm config get registry
如果速度慢或者经常超时,配置为镜像源。
第四步,进入 OpenClaw 项目目录,执行依赖安装:
bash复制npm ci
这里推荐 npm ci 而不是 npm install,理由前面说过:它能保证依赖树和 lock 文件完全一致。
第五步,启动 OpenClaw:
bash复制npm run dev
如果启动失败,去看日志文件。OpenClaw 通常会在项目目录的 logs 文件夹里输出日志,里面记录的报错信息比终端里看到的更完整。很多人启动失败后只看终端输出,其实很多时候终端只显示了一个表面错误,真正的堆栈在日志里。
4.2 高频报错速查表
我把实际遇到过的、以及社区里常见的报错整理成一张表,方便你遇到问题时直接对照。但注意:报错表现相同,根源不一定相同,表里给的是最可能的修复方向。
| 报错现象 | 最可能的原因 | 解决方向 |
|---|---|---|
| npm : 无法加载文件 ...npm.ps1,因为在此系统上禁止运行脚本 | PowerShell 执行策略限制 | Set-ExecutionPolicy RemoteSigned |
| CategoryInfo : NotSpecified: (npm error co... | PowerShell 对原生命令错误输出的包装,不是真正错误 | 看后面的 npm error 具体内容,通常伴随执行策略问题 |
| npm 不是内部或外部命令 | Node.js 未安装或 PATH 未配置 | 重装 Node.js,勾选 Add to PATH |
| OpenClaw 启动报 node runtime not found | Node 版本切换导致路径失效 | nvm use 切回原版本,或重装 Node |
| agent failed before reply: unknown model: xxx | 模型 ID 配置错误 | 去模型平台文档查准确 model id |
| OpenClaw control UI did not start | 端口被占用或前端依赖未装完 | 改端口,或者删掉 node_modules 重新 npm ci |
这张表里的每一条,我都实际排查过至少一次。尤其是第一行,它在各种 Windows 开发群里出现的频率高得惊人。只要你的终端是 PowerShell 且执行策略是 Restricted,这个报错就会一直跟着你,直到你改掉策略为止。
4.3 我在 Windows 上部署 OpenClaw 时踩过的坑
最后分享几个我自己的教训,希望能帮你少走弯路。
第一,不要一上来就加 --force。遇到依赖冲突时,--force 确实能装完,但装完之后你可能会在一个“看似成功实则残缺”的环境里调试很久。我试过用 --force 装完 OpenClaw 后,启动时各种找不到模块,最后只能删掉 node_modules 重来。先用 --legacy-peer-deps 试试,这个参数在依赖树老冲突的项目里非常管用,装出来的环境也更接近正常状态。
第二,用 nvm-windows 管好 Node 版本。OpenClaw 部署时最好固定到 Node 20 LTS,不要随便切到最新版。因为很多依赖的原生模块在最新 Node 上可能还没有预编译二进制,会现场编译,一旦编译环境缺少 Visual Studio Build Tools,就直接失败。我吃过这个亏,后来固定版本之后,这个问题基本没再出现过。
第三,改完执行策略要开新终端。Set-ExecutionPolicy 改完后不会立刻影响当前已经打开的 PowerShell 会话,必须新开一个窗口才生效。很多人改完策略发现 npm 还是报同样的错,以为自己没改成功,其实只是没有重开终端。
第四,启动 OpenClaw 之前先检查端口。Control UI 起不来,很可能是 3000 这种常见端口被其他程序占了。你可以用下面命令查端口占用:
powershell复制netstat -ano | findstr 3000
找到占用进程 PID 后,再决定是换端口还是结束进程。这个操作虽然简单,但很多教程里不会提。
第五,项目目录路径别带中文和空格。Windows 下路径里有空格或者中文,会导致某些 Node 依赖在编译时找不到路径。把 OpenClaw 放在 D:\openclaw 这种纯英文无空格目录里,能避开大量莫名奇妙的坑。项目目录路径里的反斜杠、空格,在有些 npm lifecycle 脚本里会被解析成参数分隔,从而报错。
OpenClaw 的部署链路其实不复杂,但 Windows 环境下的这些小坑叠加起来,确实会让人心态爆炸。按着上面的排查顺序来,先修执行策略,再处理源和版本,最后看模型配置,绝大多数问题都能在半小时内解决。你部署时如果还碰到其他奇葩报错,可以把日志文件翻出来,顺着里面第一条真正的 error 信息去查,比在终端里看那些 CategoryInfo : NotSpecified 之类的壳信息有效得多。
