OpenClaw 报错 Unable to resolve bundled plugin speech-core/runtime-api.js:从定位到修复的完整排查记录
1. 先别急着删库这个报错到底卡在哪一环OpenClaw 启动时抛出Unable to resolve bundled plugin speech-core/runtime-api.js本质是插件解析链路在“内置插件运行时入口”这一步断了。OpenClaw 的插件分两类一类是随主包分发的 bundled plugin比如 speech-core、discord-core 这些另一类是用户自己放进 extensions 目录的外部插件。bundled plugin 不需要你单独npm install它的runtime-api.js应该躺在安装目录的dist/extensions/speech-core/下面。启动时 OpenClaw 会按注册表逐个 resolve 这些入口文件任何一个路径对不上就会把整条链路标记为失败。这个报错最迷惑人的地方在于你明明没开语音功能它却偏偏报 speech-core。原因在于 OpenClaw 的插件加载是“全量预解析”策略——网关启动阶段会把所有 bundled plugin 的 public surface 先扫一遍注册到运行时上下文里而不是等你调用语音接口才加载。所以只要 speech-core 的文件缺失或路径错位哪怕你只用文本 Agent网关也会在初始化阶段直接失败表现为Agent failed before reply。适合谁看正在用 OpenClaw 搭本地 Agent 网关、跑 Discord/Telegram 机器人、或者刚升级完版本发现启动不了的同学。我试过在 Windows 和 Linux 两种环境下复现触发条件高度一致下面把定位命令和修复配置都拆开讲。先建立一个判断顺序避免上来就重装现象大概率原因优先动作openclaw --version正常仅插件报错插件目录文件缺失/路径错配检查 dist/extensionsopenclaw --version也报错主包安装损坏重装主包升级后首次启动报错新旧版本文件混用清理后重装报错里带Cannot find module ...openclaw.mjs核心入口丢失彻底卸载重装这张表是我踩过几次坑之后总结的核心逻辑是先确认 CLI 本身活着再谈插件。如果连openclaw --version都跑不出来那问题根本不在 speech-core而是主包安装层已经烂了这时候去改插件配置纯属浪费时间。还有一个容易忽略的点OpenClaw 的插件解析对路径大小写和斜杠方向敏感。Windows 下如果用某些解压工具手动挪过node_modules可能出现Speech-Core和speech-core并存的情况resolve 时按注册表里的小写名去找自然找不到。这类问题用openclaw doctor不一定能自动修得手动核对目录名。所以第一步不是急着敲修复命令而是把“报错发生在哪一层”确认清楚。下一节先讲怎么用 TaoToken 把模型侧配置理顺因为很多同学在修插件的同时模型接入的 Base URL 和 Key 也是乱的两边一起排查效率更高。2. 用 TaoToken 把模型接入层先理顺插件报错和模型接入看起来是两件事但实际排查时经常纠缠在一起。OpenClaw 的 Agent 会话失败日志里既有Unable to resolve bundled plugin也可能夹着模型请求 401 或local proxy failed。如果你一边修插件一边还在怀疑是不是 Key 配错了排查会非常痛苦。我的做法是先把模型接入层用 TaoToken 固定下来确保这部分是干净的再去动插件目录。TaoToken 在这里的角色是统一模型入口。你不需要在 OpenClaw 里为每个模型单独配一套鉴权而是把 Base URL 指向https://taotoken.net/api用同一个 Key 去调不同模型。这样排查插件问题时模型侧只有一个变量不会互相干扰。具体操作路径打开https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentopenclaw_speech_core创建 API Key。在 OpenClaw 的模型配置里填入 Base URL 和 Key。用https://taotoken.net/api作为统一入口不要带 UTM 后缀那是给页面跳转用的。如果你用的是 Claude Code 或 Cline 这类工具配置逻辑一样只是配置文件位置不同。OpenClaw 的模型配置通常在~/.openclaw/config.json或项目根目录的openclaw.config.json里字段名可能是baseUrl、apiKey、model。下面给一个可复制的 JSON 片段路径按你实际安装位置调整{ model: { provider: openai-compatible, baseUrl: https://taotoken.net/api, apiKey: sk-你的TaoToken密钥, modelId: claude-sonnet-4-20250514 }, plugins: { speech-core: { enabled: true, runtimePath: ./dist/extensions/speech-core/runtime-api.js } } }注意runtimePath这一项很多同学报Unable to resolve就是因为这里写的是绝对路径但换机器或升级后路径变了。建议用相对路径或者干脆删掉这一项让 OpenClaw 走默认解析。默认解析会去dist/extensions/plugin-name/runtime-api.js找只要文件在就能加载。模型侧验证是否通了可以用模型对话页面直接测https://taotoken.net/model-chat?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentopenclaw_speech_core。发一句“你好”能正常返回就说明 Base URL 和 Key 没问题。这一步过了再回去看插件报错就能确定问题纯粹在 OpenClaw 本地文件层。如果你打算长期跑 Agent 任务比如让 OpenClaw 持续处理消息队列可以考虑 Coding Plan入口在https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentopenclaw_speech_core。它的好处是额度稳定不会因为单次请求波动导致 Agent 中途断掉排查插件时少一个干扰项。模型接入层理顺之后接下来才是真正的插件目录检查。记住一个原则模型侧只留一个变量插件侧只改一个路径两边不要同时动。3. 可复制的插件目录检查与 runtime-api.js 路径修复这一节是核心操作。先给一套完整的检查命令按顺序执行每一步的输出都决定下一步怎么走。3.1 确认 OpenClaw 安装根目录不同安装方式根目录不一样。npm 全局安装通常在WindowsC:\Users\用户名\AppData\Roaming\npm\node_modules\openclawmacOS/Linux/usr/local/lib/node_modules/openclaw或~/.npm-global/lib/node_modules/openclaw用命令直接定位npm root -g输出就是全局 node_modules 路径后面拼/openclaw即可。进入这个目录cd $(npm root -g)/openclaw ls -la你应该能看到dist/、package.json、openclaw.mjs这些。如果openclaw.mjs不在说明主包安装不完整直接跳到 3.5 重装。3.2 检查 speech-core 插件目录ls -la dist/extensions/speech-core/正常应该看到runtime-api.js、index.js、package.json等。如果这个目录不存在或者runtime-api.js缺失就是报错的直接原因。再确认文件确实可读cat dist/extensions/speech-core/runtime-api.js | head -20能打印出内容说明文件完好。如果报No such file or directory就是文件丢了。3.3 核对插件注册表OpenClaw 内部有一份 bundled plugin 注册表通常在dist/extensions/registry.json或类似位置。查看cat dist/extensions/registry.json | grep -A3 speech-core确认里面登记的路径和实际文件路径一致。如果注册表写的是speech-core/runtime-api.js但实际文件在dist/extensions/speech-core/runtime-api.js那解析基准目录就很重要。OpenClaw 默认以dist/extensions/为基准所以注册表里的相对路径应该是speech-core/runtime-api.js。3.4 修复配置如果文件在但配置里runtimePath写错了改配置文件。以openclaw.config.json为例{ plugins: { speech-core: { enabled: true, runtimePath: speech-core/runtime-api.js } } }注意这里不要写./dist/extensions/前缀因为 OpenClaw 会自己拼基准目录。写了反而变成dist/extensions/dist/extensions/speech-core/runtime-api.js照样报Unable to resolve。如果你用的是 TOML 配置部分版本支持写法[plugins.speech-core] enabled true runtimePath speech-core/runtime-api.js改完保存不要急着启动先跑一次诊断openclaw doctor --fixdoctor 会扫描插件目录把无效的 runtimePath 隔离掉并输出它认为正确的路径。如果 doctor 也报Cannot find module ...openclaw.mjs说明主包已经损坏直接走重装。3.5 重装主包npm uninstall -g openclaw npm cache clean --force npm install -g openclaw卸载时如果遇到EPERM权限警告通常是文件被占用关掉正在运行的 OpenClaw 进程和杀毒软件实时扫描再重试。重装完成后openclaw --version能打印版本号说明主包恢复。然后再检查插件目录openclaw plugins list --enabled --verbose这个命令会列出所有已加载的 bundled pluginspeech-core 应该在列表里且状态是 enabled。如果它显示 missing 或 error继续看下一节。3.6 版本错配的处理如果你是从 Beta 版降级或升级过来可能出现新旧文件混用。典型表现是dist/extensions/下同时存在speech-core和speech-core.bak或者runtime-api.js是旧版本的。处理方式rm -rf dist/extensions/speech-core npm install -g openclaw2026.4.29指定一个稳定版本重装让 npm 重新拉取完整的 dist 目录。装完再跑openclaw plugins inspect speech-core --runtime --json看输出的resolvedPath是否指向真实存在的文件。这一套下来大部分Unable to resolve bundled plugin speech-core/runtime-api.js都能解决。核心就一句话文件要在路径要对注册表要一致。三者缺一就会报这个错。4. 重启网关并验证插件加载成功配置改完、文件补齐之后不能只看日志不报错就完事要确认插件真的注册进运行时了。下面是一套验证动作按顺序做。4.1 启动网关并跟踪日志openclaw gateway --verbose另开一个终端跟踪日志openclaw logs --follow观察启动阶段有没有speech-core相关的 resolve 记录。正常输出类似[plugin] resolving bundled plugin speech-core [plugin] runtime entry resolved: /path/to/dist/extensions/speech-core/runtime-api.js [plugin] speech-core registered如果看到Unable to resolve再次出现说明路径还是不对回到第 3 节重新核对。4.2 用 inspect 命令确认运行时状态openclaw plugins inspect speech-core --runtime --json输出是一个 JSON重点看三个字段{ id: speech-core, enabled: true, resolvedPath: /usr/local/lib/node_modules/openclaw/dist/extensions/speech-core/runtime-api.js, status: loaded }status是loaded才算成功。如果是missing或errorresolvedPath会显示它尝试找的路径拿这个路径去文件系统里核对就能定位差在哪一级目录。4.3 触发一次 Agent 会话插件加载成功不代表 Agent 会话一定通还要验证模型侧和插件侧协同工作。发一条测试消息openclaw agent send --message 测试会话如果返回正常回复说明整条链路通了。如果返回Agent failed before reply但日志里没有Unable to resolve那问题就转移到模型接入层回去检查第 2 节的 Base URL 和 Key。4.4 检查端口占用网关默认端口 18789确认它真的在监听netstat -ano | findstr :18789Windows 下用findstrmacOS/Linux 用grep。有 LISTENING 状态说明网关起来了。如果端口被占用换端口启动openclaw gateway --port 187904.5 验证插件列表openclaw plugins list --enabled --verbose输出里 speech-core 应该显示 enabled且没有 warning。如果它显示 disabled检查配置文件里是不是被手动关了。有些同学在排查时把enabled改成 false修完忘了改回来结果插件不加载又以为是路径问题。4.6 长期运行的稳定性检查如果你打算让网关常驻建议加一个定时诊断openclaw doctor --fix可以写成 cron 或计划任务每天跑一次。doctor 会清理过时的插件状态隔离无效配置避免某次升级后文件错位又导致启动失败。我自己的做法是每周跑一次配合日志轮转基本没再遇到过Unable to resolve这类问题。验证这一步的关键是不要只看“没报错”要看“状态是 loaded”。日志不报错可能只是错误被吞了inspect 的 JSON 输出才是硬证据。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth修speech-core/runtime-api.js的过程中很容易顺带撞上其他报错。这一节把高频错误和对应动作列清楚避免你在一堆日志里迷失。5.1 401 Unauthorized现象Agent 会话返回 401日志里模型请求被拒。原因TaoToken 的 Key 没填对或者 Base URL 写成了带 UTM 的页面地址。注意 API 入口是https://taotoken.net/api不要带?utm_source...那串那是给网页跳转用的API 请求带上会解析失败。修复检查配置文件里的apiKey和baseUrlKey 重新从https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentopenclaw_speech_core复制一次确保没有多余空格。5.2 local proxy failed现象日志出现local proxy failed模型请求发不出去。原因OpenClaw 本地代理层配置了错误的转发地址或者端口冲突。常见于同时开了多个网关实例。修复确认只有一个 gateway 进程在跑检查netstat看端口占用。如果配置里写了自定义 proxy先注释掉走直连https://taotoken.net/api测试。5.3 reading choices 报错现象Cannot read properties of undefined (reading choices)。原因模型返回体格式和 OpenClaw 预期不一致。通常是 Base URL 指向了一个不兼容 OpenAI 格式的端点或者模型 ID 写错导致返回了错误结构。修复确认baseUrl是https://taotoken.net/apimodelId用平台支持的模型名。用模型对话页面先测一次确认返回结构正常再填回 OpenClaw。5.4 OAuth 相关报错现象OAuth token expired或OAuth callback failed。原因如果你用的是 Claude Code 或 Codex 这类带 OAuth 的工具token 过期或回调地址不对。修复重新走一次授权流程。如果是 Codex 的auth.json确认里面的base_url指向https://taotoken.net/apiapi_key字段填 TaoToken 的 Key。三件套要齐全Base URL、Key、Model ID缺一个都会报错。5.5 插件报错和模型报错同时出现这是最麻烦的情况。日志里既有Unable to resolve bundled plugin又有 401。处理顺序先修插件再修模型。因为插件加载失败会导致网关初始化中断模型请求根本发不出去这时候看到的 401 可能是假象。修完插件重启网关确认plugins inspect状态是 loaded再发测试消息。如果这时才出现 401那才是真的 Key 问题。5.6 对照表报错根因动作Unable to resolve bundled plugin插件文件缺失/路径错检查 dist/extensions修 runtimePath401Key 或 Base URL 错重填 TaoToken KeyBase URL 用 /apilocal proxy failed代理配置冲突关多余进程走直连reading choices返回体格式不符核对 modelId 和 baseUrlOAuth failedtoken 过期重新授权检查 auth.json这张表建议存下来下次遇到直接对号入座。核心原则还是那句先确认 CLI 活着再确认插件加载最后确认模型通。顺序反了排查时间翻倍。6. 把配置固定下来下次升级不慌修好之后建议做两件事避免下次升级又踩同样的坑。第一把当前可用的配置备份一份。OpenClaw 的配置文件、插件目录列表、TaoToken 的 Base URL 和 KeyKey 不要明文提交到 git存到一个本地笔记里。升级前先对比升级后如果报错直接回滚配置。第二升级前先跑openclaw doctor --fix让它把当前状态记录一遍。升级后再跑一次对比输出差异。如果 doctor 报出新的 missing 插件提前处理不要等启动失败才动手。如果你需要长期跑 Agent模型侧用 Coding Plan 固定额度入口在https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_contentopenclaw_speech_core。插件侧保持dist/extensions/目录干净不要手动往里塞文件所有 bundled plugin 都让 npm 安装时自动铺好。最后给一个日常检查命令贴在终端里随时跑openclaw --version openclaw plugins inspect speech-core --runtime --json | grep status输出loaded就放心用。如果哪天又看到Unable to resolve回到第 3 节从ls dist/extensions/speech-core/开始查五分钟内能定位。