
1. 先复现2026.3.22 升级后 Control UI assets not foundOpenClaw 升到 2026.3.22 之后网页控制面板直接打不开浏览器里一片空白gateway 日志里反复出现 Control UI assets not found. Build them with pnpm ui:build。这行提示很容易把人带偏——第一反应是本地没执行前端构建于是去项目目录里 pnpm ui:build跑完再打开还是白屏。真正的问题不在构建命令而在 2026.3.22 的 npm 包里少了一个目录。这篇按排障顺序来先复现报错再用 npm pack --dry-run 把 2026.3.13 和 2026.3.22 两个版本的文件清单摊开对比找到缺失的 dist/control-ui从旧版 tgz 里解出来拷回全局 node_modules/openclaw/dist/最后 openclaw gateway restart。等控制面板恢复模型通道可以顺手收到 TaoToken去 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 注册并创建 API KeyBase URL 填 https://taotoken.net/apiOpenClaw 的对话和 gateway 请求就走统一入口。注意TaoToken 在这里只负责供 Key 和 Base URL不补目录、也不接管 UI 构建。1.1 控制面板白屏时先看 gateway 日志复现环境很普通一台开发机Node 版本没换包管理器也没换唯一变化就是 OpenClaw 从 2026.3.13 升到了 2026.3.22。升级命令本身不报错安装输出看起来一切正常。启动 gateway 之后Web 控制面板的地址能打开但页面不渲染控制台里能看到加载 control-ui-assets-xxx.js 的请求返回 404 或者直接空白。真正有用的是 gateway 进程的日志。日志里会滚出类似下面的内容Control UI assets not found. Build them with pnpm ui:build第一次看到这行大多数人的判断是项目源码里没有构建前端产物。但 OpenClaw 如果是通过 npm 全局安装的控制面板资源本来就该随包发布而不是让用户每次安装后再跑一次 pnpm ui:build。也就是说这行报错描述的是“资源没找到”不是“你必须现在去构建”。它只是把最常见的解决方法印在错误信息里容易造成误导。要确认是不是包本身的问题可以先看全局安装目录里 dist 下面到底有什么。不同系统路径不一样先拿到 npm 全局根目录npm root -g假设输出是 /usr/local/lib/node_modules那么 OpenClaw 的安装位置就是 /usr/local/lib/node_modules/openclaw。进去看 distls -la /usr/local/lib/node_modules/openclaw/dist如果只看到 control-ui-assets-xxx.js 和 control-ui-shared-xxx.js 这类零散文件却没有 control-ui 目录那基本就对上了2026.3.22 的 npm 包漏发了整个 dist/control-ui 目录。控制面板真正需要的是目录里的多个静态文件而不是两个被拆出来的 js。1.2 为什么 pnpm ui:build 不是这次的正解在源码仓库里pnpm ui:build 确实会生成控制面板资源。但排障要先分清安装方式从 git 仓库拉源码、自己 pnpm install、pnpm build 的运行方式构建命令有意义。用 npm install -g openclaw 安装的方式包内应该自带 dist/control-ui不该要求用户进入全局 node_modules 去跑 pnpm ui:build。这次升级只改了版本号没有改构建流程2026.3.13 能用2026.3.22 不能用说明差异在发布产物。所以先不去全局目录里乱跑构建。更稳的路径是把两个版本的 npm 包拿下来用 npm pack --dry-run 看文件清单确认 2026.3.22 到底少了什么。确认之后再决定是补目录还是降级。这也是后面几节的主线。这里插一句模型通道的事。控制面板恢复之后OpenClaw 还需要能访问模型。以前要分别去不同模型厂商注册、拿 Key、配不同 Base URL现在可以统一到 TaoToken打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 注册账号在控制台创建一把 API KeyBase URL 用 https://taotoken.net/api。这个地址末尾不带 /v1也不要把它和官网落地页混用。先记住这一点等第 4 节再展开配置。2. npm pack --dry-run 对比2026.3.13 与 2026.3.22 的 dist 目录差在哪2.1 把两个版本的 npm 包下载到临时目录不要直接在全局 node_modules 里做实验先开一个临时目录mkdir -p /tmp/openclaw-pack-check cd /tmp/openclaw-pack-check然后分别下载两个版本的 tarball。这里以 2026.3.13 和 2026.3.22 为例实际版本号以你升级前后的 package.json 为准npm pack openclaw2026.3.13 npm pack openclaw2026.3.22命令执行完目录里会出现两个 tgz 文件比如openclaw-2026.3.13.tgz openclaw-2026.3.22.tgz如果只想看清单不实际下载也可以用 npm pack --dry-run但为了后面要从旧版里解出目录直接 pack 更省事。下载完成之后先不要解包先用 tar 列出文件列表tar -tzf openclaw-2026.3.13.tgz | sort files-2026.3.13.txt tar -tzf openclaw-2026.3.22.tgz | sort files-2026.3.22.txt再用 diff 对比diff -u files-2026.3.13.txt files-2026.3.22.txt | less重点看 package/dist/ 下面的差异。如果 diff 输出太长直接过滤 control-uigrep control-ui files-2026.3.13.txt grep control-ui files-2026.3.22.txt2.2 用 --dry-run 看文件清单锁定 dist/control-ui如果更习惯 npm 原生命令可以这样看单个版本的文件清单npm pack openclaw2026.3.13 --dry-run npm pack openclaw2026.3.22 --dry-run输出里会列出即将打包的文件和目录。对比时会发现2026.3.13 的清单里有大量 package/dist/control-ui/ 开头的条目比如package/dist/control-ui/index.html package/dist/control-ui/assets/... package/dist/control-ui/...而 2026.3.22 的清单里control-ui 相关的只剩两个文件package/dist/control-ui-assets-xxx.js package/dist/control-ui-shared-xxx.js目录整个消失。问题就在这里控制面板加载时需要 dist/control-ui 这个目录下的静态资源但 2026.3.22 的发布包没有包含它。两个零散 js 文件不足以支撑页面渲染所以浏览器只能白屏gateway 只能打印 Control UI assets not found。2.3 2026.3.22 只剩两个 control-ui 相关 js 文件为了确认不是过滤条件写错可以把两个版本的 dist 目录单独列出来tar -tzf openclaw-2026.3.13.tgz | grep ^package/dist/ | head -50 tar -tzf openclaw-2026.3.22.tgz | grep ^package/dist/ | head -502026.3.13 的 dist 下面会看到 control-ui 目录里面还有子目录和多个文件2026.3.22 的 dist 下面只剩那两个 js再加上其他与 UI 无关的内容。到这里可以下一个明确结论不是本地构建坏了是 npm 包漏发了 dist/control-ui。这个结论也解释了为什么“重新安装一遍”没用。只要安装源还是 2026.3.22装多少次都不会把缺失目录装回来。接下来有两条路降到 2026.3.13或者从 2026.3.13 的 tgz 里把目录补到 2026.3.22 的全局安装目录。降级最省事但可能丢掉 2026.3.22 的其他修复补目录能保留当前版本代价是手动操作一次。下面走补目录这条。这里再提一次模型通道的事补目录只解决控制面板不解决 OpenClaw 调用模型时用什么 Key。等 gateway 重启成功去 TaoToken 创建 API Key模型广场里选一个可用模型 ID再把 Base URL 填到 OpenClaw 的模型配置里。具体填法在第 4 节先把第 3 节的目录补完。3. 从 2026.3.13 的 tgz 里补齐 dist/control-ui 并重启 gateway3.1 找到全局 node_modules/openclaw 的实际路径补目录之前先确认 OpenClaw 到底装在哪里。前面已经用过 npm root -g这里再确认一次npm root -g把输出记为 GLOBAL_ROOT。OpenClaw 目录通常是GLOBAL_ROOT/openclaw可以用下面的命令直接定位OPENCLAW_DIR$(npm root -g)/openclaw echo $OPENCLAW_DIR ls -la $OPENCLAW_DIR/dist如果 ls 的输出里没有 control-ui 目录只有 control-ui-assets-xxx.js 和 control-ui-shared-xxx.js那就和前面 npm pack 的结论一致。接下来要做的是把 2026.3.13 tgz 里的 package/dist/control-ui 解出来然后拷到 OPENCLAW_DIR/dist/ 下面。注意不要直接覆盖整个 dist只补缺失的 control-ui 目录避免把 2026.3.22 的其他文件替换掉。操作前可以先备份一下当前 distcp -a $OPENCLAW_DIR/dist $OPENCLAW_DIR/dist.bak-2026.3.223.2 解包旧版 tgz拷贝目录回到临时目录 /tmp/openclaw-pack-check解包 2026.3.13 的 tgzmkdir -p old-2026.3.13 tar -xzf openclaw-2026.3.13.tgz -C old-2026.3.13解完之后会得到 old-2026.3.13/package/。确认 control-ui 目录存在ls -la old-2026.3.13/package/dist/control-ui然后把它拷到全局安装目录OPENCLAW_DIR$(npm root -g)/openclaw cp -a old-2026.3.13/package/dist/control-ui $OPENCLAW_DIR/dist/拷完再确认ls -la $OPENCLAW_DIR/dist/control-ui应该能看到 index.html、assets 目录等一堆文件而不是只有两个 js。到这一步缺失的资源已经补回 2026.3.22 的安装目录。如果团队里多台机器都要修可以把这一步写成一个临时脚本但不要提交到项目仓库里当构建流程。它只是针对 2026.3.22 这个特定发布包的补救。等官方后续版本把目录补回直接升级即可不需要长期维护这个脚本。3.3 openclaw gateway restart 与页面验证目录补齐后必须重启 gateway否则进程还拿着旧的路径判断。重启命令openclaw gateway restart重启完成后再看日志。如果不再出现 Control UI assets not found就可以打开 Web 控制面板。建议用无痕窗口或者强制刷新一次避免浏览器缓存旧的 404 结果打开控制面板地址。按 CtrlShiftR 或 CmdShiftR 强制刷新。看 Network 面板里 control-ui 目录下的资源是否 200。随便点一个面板功能确认没有其他静态资源报错。如果页面仍然白屏先别急着怀疑补目录失败检查 gateway 进程是不是真的重启了。可以用下面的命令看进程和端口ps aux | grep openclaw openclaw gateway status另一个常见问题是全局安装和本地项目安装混用。如果你在项目目录里跑 openclaw而项目 node_modules 里也有一个旧版本或新版本的 openclaw实际启动的可能不是全局那份。确认当前使用的是哪个which openclaw npm ls -g openclaw补目录时也要补到实际被使用的那份 node_modules/openclaw/dist 下面。控制面板恢复之后OpenClaw 的 UI 问题就结束了。但 gateway 能跑起来不等于能对话下一步要给它一个可用的模型通道。以前是分别去不同厂商申请 Key现在统一到 TaoToken打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 注册并创建 Key后面配置只用改 Base URL 和 Key 两个值。4. 面板恢复后把 OpenClaw 的模型通道接到 TaoToken4.1 去官网创建 API Key确认模型 ID控制面板能打开之后先处理模型凭证。打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 注册账号进入控制台。在 API Keys 页面创建一把新 Key复制出来先放在安全的地方。本文所有示例都用占位符 YOUR_API_KEY不要把自己真实的 Key 贴到文章、聊天记录或者公开仓库里。接着确认模型 ID。模型 ID 不要凭记忆写也不要用网上看到的旧名称。打开 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 的模型广场看当前列表里有哪些可用模型挑一个适合 OpenClaw 对话或代码场景的 ID复制下来。后面配置文件里的模型字段就填这个 ID。如果模型广场更新了列表以页面当时展示为准。OpenClaw 这边需要准备两个值Base URLhttps://taotoken.net/apiAPI KeyYOUR_API_KEY注意 Base URL 末尾不要加 /v1也不要把官网落地页的 UTM 参数带进来。官网链接是给人打开注册、创建 Key、看模型广场用的填进 OpenClaw 配置的是接口地址两者不要混。4.2 在 OpenClaw 配置里填 Base URL 与 KeyOpenClaw 的模型配置路径和字段名可能随版本变化下面以常见的 ~/.openclaw/config.json 为例。先备份原配置cp ~/.openclaw/config.json ~/.openclaw/config.json.bak然后编辑配置文件把 TaoToken 作为一个 provider 加进去。示例结构如下实际字段名以你本机 OpenClaw 版本的配置说明为准{ providers: { taotoken: { type: openai-compatible, baseURL: https://taotoken.net/api, apiKey: YOUR_API_KEY, models: [ 以模型广场当时列表为准的模型 ID ] } }, agent: { model: taotoken/以模型广场当时列表为准的模型 ID } }如果 OpenClaw 使用环境变量来覆盖 provider 配置也可以这样写export OPENCLAW_PROVIDER_BASE_URLhttps://taotoken.net/api export OPENCLAW_PROVIDER_API_KEYYOUR_API_KEY但环境变量方式要注意作用域只对当前 shell 和它启动的 gateway 生效。如果你用 systemd、launchd 或者容器启动 OpenClaw要把变量写到对应的服务配置里而不是只写在终端里。配置保存后重启 gateway 让新配置生效openclaw gateway restart再打开控制面板随便发一条消息测试。如果返回正常说明 Base URL、Key 和模型 ID 三个值都对上了。4.3 发消息验证区分两个地址验证分两层第一层是控制面板能打开说明 dist/control-ui 补好了。第二层是发消息能收到回复说明模型通道通了。两层都通过才算这次排障完整结束。验证时可以故意在模型广场里换一个模型 ID 再试一次确认配置里读的是同一套 Base URL 和 Key。如果换模型后报模型不存在大概率是模型 ID 写错而不是 Key 无效。这里再强调一次两个地址的区别注册账号、创建 API Key、看模型广场、看用量https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end填进 OpenClaw 配置的 Base URLhttps://taotoken.net/api后者末尾不带 /v1也不加任何 UTM 参数。很多配置失败不是 Key 的问题而是把官网落地页地址误填到了 baseURL 字段。如果团队里有多个人共用一台 gateway建议每人用自己的 Key而不是共用一把。这样在控制台能看到各自的调用记录出问题也容易定位。Key 的创建入口在 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 创建后按上面的方式写进配置即可。5. 还没恢复怎么办几个与 dist/control-ui 相关的检查点5.1 目录拷了但 gateway 没重启补完 dist/control-ui 之后如果直接刷新浏览器页面仍可能白屏。因为 gateway 进程在启动时已经判断过资源目录不存在不重启不会重新扫描。执行openclaw gateway restart然后用 openclaw gateway status 确认进程是新的。如果重启命令没有真正杀掉旧进程可以用系统工具查一下端口占用lsof -i :端口号把旧进程结束掉再启动。控制面板地址后面如果带端口以你本机 gateway 配置为准。5.2 全局安装与本地项目安装混用第二个检查点是安装位置。有的开发机同时存在npm 全局安装的 openclaw某个项目 node_modules 里的 openclawpnpm 全局安装的 openclaw补目录时要补到实际运行的那一份。用 which openclaw 和 npm root -g 交叉确认。如果实际运行的是项目本地版本补全局目录不会生效需要去项目里的 node_modules/openclaw/dist 下面补。或者更干净的做法在项目里重新安装 2026.3.13先让面板恢复再等官方修复 2026.3.22 的发布包。5.3 模型通道 401 / 404 的快速对照控制面板恢复后如果发消息报错常见的两类是401Key 不对、Key 被禁用、或者环境变量没生效。确认配置里写的是 YOUR_API_KEY 对应的真实 Key且 gateway 重启过。404Base URL 写错。重点检查是不是写成了 https://taotoken.net/api/v1或者把官网落地页地址填进了 baseURL。正确写法是 https://taotoken.net/api末尾没有 /v1也没有 UTM 参数。模型 ID 不存在时有的接口会返回 404 或类似“model not found”的信息。这时去 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end 的模型广场核对当前可用 ID不要用记忆里的旧名称。如果控制面板又出现 Control UI assets not found先检查 dist/control-ui 目录是不是被后续的 npm 操作覆盖掉了。重新执行第 3 节的拷贝步骤再重启 gateway。排障到这里两个独立问题都有了明确边界UI 资源缺失靠补 dist/control-ui 解决模型通道靠 TaoToken 的 Key 和 Base URL 解决。两者不要混在一起排查否则很容易在错误的方向上浪费时间。配好之后建议先去 TaoToken 模型对话 用同一把 Key 发一条测试消息确认模型 ID 和 Base URL 没问题如果打算长期在 OpenClaw 里写代码或跑 agent可以看 Coding Plan 的套餐是否够用。Key 随时可以在 控制台 API Keys 里重建OpenClaw 这边只要同步更新配置文件里的 apiKey 字段即可。