升级 OpenClaw 这种事,正常来说应该是平滑的:拉新版本、重启服务、继续用。但 v2026.3.22 这次升级,我前后折腾了两个晚上,核心问题就两个——飞书插件静默失联,Control UI 直接白屏连不上。更烦的是,升级过程中那条legacy exec approvals exist at /root/.openclaw/exec-approvals.json的提示,让不少人在社区里反复追问到底要不要处理。这篇文章把我自己的完整排查链路、踩坑细节、以及最终验证通过的修复方案整理出来。如果你也正准备升级 v2026.3.22,或者升级完已经开始报错,这篇排障记录应该能帮你省下不少时间。
1. 为什么这次升级容易出问题:v2026.3.22 动了哪些底层逻辑
1.1 版本号背后的信号
v2026.3.22 这个版本号,按 OpenClaw 的命名规则来看,2026.3 是发布周期,22 是当月的构建序号。但真正值得关注的不是数字本身,而是这个版本集中改动了两条关键链路:插件配置的加载方式和本地控制服务的启动逻辑。
先说插件加载。旧版本的飞书、微信这类通信插件,配置基本都平铺在config.toml里,插件自己负责解析 app_id、app_secret 这些字段。v2026.3.22 开始,OpenClaw 把插件配置纳入了统一的 profile 体系,也就是说插件不再直接读取 config 根节点下的[plugins.feishu]这种结构,而是要求配置按[profiles.default.plugins.feishu]的层级去组织。如果你直接拿旧配置启动,OpenClaw 不会报错——它会静默跳过格式不匹配的插件配置。这就解释了为什么很多人升级后飞书机器人"看起来一切正常,但消息就是发不出去"。
再说 Control UI。旧版本的 Control UI 是一个简单的本地 Web 服务,默认监听127.0.0.1:8080,启动时打印一个 token,直接访问就行。v2026.3.22 把 UI 服务拆成了独立进程管理,并且引入了端口动态分配和持久化 token 机制。听起来是好事,但实际升级过程中,端口监听地址的变更、token 的缓存策略、以及浏览器端 Service Worker 对旧页面的缓存,这三样叠加在一起,就很容易让人误判为"升级把 UI 搞坏了"。
1.2 升级前必须做的三件事
如果你现在还没有升级,那我强烈建议你先做三件事,能省掉后面 80% 的麻烦。
第一,备份配置目录。~/.openclaw/(Windows 上通常是C:\Users\<用户名>\.openclaw\)下至少有四个东西要备份:config.toml、exec-approvals.json、plugins/目录、以及整个workspace/。不要只备份 config,因为飞书插件的凭证信息、历史审批记录都可能散落在其他文件里。
第二,记录当前版本和插件列表。升级前运行一次openclaw --version和openclaw plugins list,把输出保存下来。升级后如果插件丢了或者版本变了,至少能对比出差异。
第三,确认飞书开放平台后台的回调地址。升级后如果插件配置层级变了,回调地址大概率需要跟着调整。提前截图保存旧的回调地址和验证 token,后面会用到。
我当时就是因为跳过了第二步,导致升级后飞书插件加载异常时,根本不知道是插件本身的问题还是配置迁移的问题,白折腾了很久。
2. 飞书插件静默失联:从日志反推配置层级变更的完整过程
2.1 现象描述:不是报错,而是"无反应"
这次飞书插件的问题非常隐蔽。升级完 v2026.3.22 之后,我给飞书机器人发消息,它完全没有任何反应。不是报错,不是超时,就是纯粹的"无反应"。去飞书开放平台后台看事件订阅的请求日志,发现 OpenClaw 这边根本没有收到任何回调。
这个现象的关键在于:插件加载成功了,但配置没有被正确解析。OpenClaw 的插件系统在启动时会扫描插件声明文件,插件存在就能加载,但插件内部的配置读取是独立的。如果配置格式不匹配,插件会以默认配置运行——对于飞书插件来说,默认配置里没有 app_id 和 app_secret,自然无法通过飞书服务端的验签,回调请求会在更早的环节被丢弃。
2.2 排查第一步:确认插件加载状态
我先看的不是飞书后台,而是本地日志。定位 OpenClaw 日志目录的方法很简单:
- Linux/macOS:
~/.openclaw/logs/ - Windows:
C:\Users\<用户名>\.openclaw\logs\
在日志目录里找最新的runtime.log,用grep -i feishu过滤关键信息。我当时看到的内容大致是:
[2026-03-23T10:12:33Z] INFO plugin loader: plugin "feishu" loaded [2026-03-23T10:12:33Z] WARN plugin feishu: config section [plugins.feishu] not found, using default [2026-03-23T10:12:33Z] WARN plugin feishu: app_id is empty, incoming message verification disabled第一条说明插件加载成功了;第二条说明它没找到老格式的配置;第三条是致命提示——app_id 为空,消息验签被禁用。看到这里,问题已经定位了:不是插件丢了,是配置没被读到。
2.3 排查第二步:在 OpenClaw 侧验证飞书回调路由
紧接着我再跑了一遍openclaw doctor命令,它的输出里有一项是插件健康检查,飞书插件那一行的状态是DEGRADED,提示信息是config missing or invalid。同时openclaw plugins list的输出显示 feishu 的加载状态是loaded (default config)。
这两条交叉验证,基本确认了问题的性质:配置文件的格式与 v2026.3.22 的解析器不兼容。这不是你配置写错了,而是升级后 OpenClaw 不再认旧格式。
2.4 根因:配置层级从扁平变成了 profile 嵌套
具体来说,旧版本飞书插件的配置长这样:
[plugins.feishu] app_id = "cli_axxxxx" app_secret = "xxxxxxxxxxxxxxxx" verification_token = "xxxxxxxxxx"v2026.3.22 要求长这样:
[profiles.default.plugins.feishu] app_id = "cli_axxxxx" app_secret = "xxxxxxxxxxxxxxxx" verification_token = "xxxxxxxxxx"差别就是多了一层profiles.default.前缀。单独看这个改动很小,但如果你在同一个配置文件里还跑了多个 profile(比如default和work),或者启用了远程配置中心,这个嵌套就很有必要——它让不同 profile 下的同名插件可以用不同凭证。
2.5 修复操作与验证
修复方法不复杂,核心是两步:改配置、重新加载。
第一步,打开config.toml,把[plugins.feishu]改成[profiles.default.plugins.feishu]。注意如果你的配置里已经有[profiles.default]段,那么应该是把plugins.feishu作为子级推进去,不要写两级。
第二步,保存后执行:
openclaw doctor --check plugins如果输出[OK] feishu: config valid,说明配置已经正确解析。
第三步,重启 OpenClaw 服务,然后去飞书开放平台后台,找到事件订阅配置,确认回调 URL 不需要变化时,手动点击"发送测试事件"。正常情况下,飞书后台会显示"回调成功",同时 OpenClaw 日志里会出现一条[INFO] feishu: webhook event received。
我验证完成后,给飞书机器人发了一条普通消息,机器人随即回复了。整个问题从定位到解决花了大概四十分钟,其中一大半时间都在确认"插件到底有没有被加载"这个前置问题上。
注意:如果你之前用的是 v2024 或更早的版本,直接升到 v2026.3.22,中间可能还隔着一次配置格式迁移。这种情况下建议先跑一次
openclaw migrate config,让它帮你把老配置转成新格式,再手动检查飞书插件的段落是否正确落到profiles层级下。
3. Control UI 白屏与连接失败:端口、token 与浏览器缓存的三种假故障
3.1 现象描述:不是打不开,就是转圈
Control UI 的问题比飞书插件更让人抓狂,因为它的现象分好几种,每一种看起来都像不同的故障。
第一种:访问http://127.0.0.1:8080,浏览器直接报"无法访问此网站"。第二种:地址能打开,但页面一直转圈,控制台报 WebSocket 连接失败。第三种:页面能打开,但提示 token 无效,让你去命令行走openclaw ui token生成新 token。这三种我都遇到了,而且是在同一次升级后的半小时内。
3.2 排查:先确认 UI 服务到底在不在跑
遇到 UI 打不开,我的建议是不要先改代码,也不要先清缓存,第一步永远是用命令行确认服务状态:
openclaw ui status这个命令会输出三样关键信息:监听地址、端口号、token 缓存位置。我执行后发现,v2026.3.22 默认监听地址变成了::1(IPv6 回环地址),而浏览器地址栏我输入的是127.0.0.1(IPv4 回环地址)。在某些系统配置下,127.0.0.1不会自动路由到::1,结果就是"服务明明在跑,但你就是连不上"。
解决办法是访问http://[::1]:8080,或者干脆在启动 UI 时指定 IPv4 地址:
openclaw ui --host 127.0.0.1 --port 8080这个参数覆盖不仅解决了 IPv4/IPv6 的歧义,也避免了端口被其他服务占用时 OpenClaw 自动换端口导致的"我明明没改配置,但地址突然变了"的困惑。
3.3 深层原因:端口动态分配和 token 持久化
v2026.3.22 的 Control UI 在启动时如果发现默认端口被占用,会随机选一个新的可用端口,并把端口号写入~/.openclaw/ui-manifest.json。这是为了避免端口冲突导致 UI 无法启动——初衷是好的,但如果你按照旧地址访问,就会觉得"升级后 UI 坏了"。
排查方法很简单:
cat ~/.openclaw/ui-manifest.json这个文件里会记录实际端口号和 token。我升级后第一次运行openclaw ui status,显示端口已经变成了35171,而我还在傻傻访问 8080。至于 token 无效的问题,v2026.3.22 不再每次启动都重新生成 token,而是优先复用ui-manifest.json里存的那个。如果你之前清过~/.openclaw/目录,或者手动删过这个文件,UI 会生成新 token,旧的收藏夹链接自然就失效了。
3.4 浏览器缓存和 Service Worker:升级后最常见的"假故障"
这是我认为最值得单独拿出来说的一节。Control UI 在 v2026.3.22 引入了 Service Worker 做本地资源缓存,目的是让 UI 在离线环境下也能快速加载。但升级后,旧的 Service Worker 可能还在继续服务旧版的前端资源,导致你打开页面看到的是旧版 JavaScript,而本地后端 API 已经换成了新版——于是页面报错,UI 看起来"坏了"。
这个时候,你在浏览器里做任何硬刷新(Ctrl+F5)都没用,因为 Service Worker 本身就有缓存策略,它会拦截网络请求直接返回缓存。
正确操作是:打开开发者工具(F12),切到 Application 面板,找到 Service Workers,点击 Unregister 注销旧 worker,然后右键刷新按钮选择"清空缓存并硬性重新加载"。
我在排查 Control UI 问题时,真正改的配置其实没有多少,绝大部分时间都花在排除这个"假故障"上。
经验之谈:升级完 Control UI 之后,如果遇到任何前端行为怪异的问题,第一件事不是改后端配置,而是开无痕窗口访问 UI。无痕模式默认禁用 Service Worker 的持久化,可以帮你快速排除缓存干扰。如果无痕窗口一切正常,那问题就锁定在浏览器缓存层面。
3.5 修复后的验证清单
我最终验证 Control UI 是否恢复正常的三个信号:
- 执行
openclaw ui status,监听地址和端口与浏览器访问地址完全一致。 - 打开 UI 页面后,Network 面板里能看到 WebSocket 连接成功,状态码 101。
- 页面上能看到实时的会话记录和插件状态,而不是一个空的旋转动画。
4. exec-approvals.json 警告:升级提示背后的审批机制变化
4.1 那条让很多人疑惑的提示
升级 OpenClaw v2026.3.22 后,如果你是 Linux 环境且使用 root 用户,大概率会在升级日志末尾看到这样一段:
legacy exec approvals exist at /root/.openclaw/exec-approvals.json. run `openclaw migrate exec-approvals` to migrate to the new approval store.社区里问这个的人很多,因为这句话看起来像是报错,但又没有阻止升级。实际上它是一个迁移提示:你之前通过openclaw approvals add添加的、或者自动记录的命令执行审批项,还在老文件里躺着,新版本希望你把它们迁移到新的存储引擎中。
4.2 为什么要迁移:审批逻辑从"静态白名单"变成了"策略集"
旧版本的exec-approvals.json其实是这样一个结构:一个 JSON 数组,每个元素记录了一条允许执行的命令模式。每次 OpenClaw 的 exec 插件要执行外部命令时,会拿命令去和这个列表做匹配,匹配上了就执行,匹配不上就弹审批请求。
v2026.3.22 开始,这个简单的白名单机制被替换成了基于策略的审批系统。新系统里,审批不再只看命令字符串,还结合会话来源、插件身份、以及命令的执行参数上下文来综合判断。好处是更安全,坏处是不兼容旧格式。
如果你不迁移,旧的审批记录仍然存在于exec-approvals.json文件里,但新版本不会读取它。结果就是你之前已经批准过的命令,升级后会重新弹出审批请求,那些自动化脚本如果恰好有需要交互确认的步骤,就可能卡住。
4.3 迁移操作与手动检查
迁移命令很简单:
openclaw migrate exec-approvals执行后,OpenClaw 会读取旧的exec-approvals.json,把里面的每一条记录转换成新格式的策略条目,并写入新的存储位置(~/.openclaw/approvals.db或类似的策略存储文件)。
迁移完成后,我建议再手动检查一下旧的 JSON 文件里有没有迁丢的内容:
cat /root/.openclaw/exec-approvals.json如果输出为空或者提示文件不存在,说明迁移已经完成。如果旧文件还在,可以先备份再删除,避免 OpenClaw 每次启动都提醒一次。
4.4 如果不想迁移,可以怎么处理
有些人的执行审批记录很少,或者升级后本来就打算重新授权,那么不迁移也可以。但要注意:不迁移的话,旧文件里的记录会全部失效。你需要做好准备,在后续使用 OpenClaw 执行命令时重新批准一遍。
我的建议是:除非你有意清空所有审批记录,否则都跑一次迁移。因为重新审批本身是个烦琐的过程,尤其是你养了一些自动化工作流之后,每一条命令都弹一次审批会很崩溃。
5. Windows 与 Linux 上的升级差异:路径、进程和环境变量的三个坑
5.1 Windows 常见问题:PATH 不生效与 workspace 路径分隔符
OpenClaw 安装后,升级过程中最常见的 Windows 问题就是 PowerShell 提示"无法将 openclaw 项识别为 cmdlet、函数、脚本文件或可运行程序的名称"。这个问题的本质是新版本的可执行文件位置变了,但系统 PATH 没有同步。
v2026.3.22 在 Windows 上的安装包会把主程序放在%USERPROFILE%\.openclaw\bin下,而老版本可能放在%LOCALAPPDATA%\Programs\OpenClaw下。升级后,老路径的程序被移除,新路径没加到 PATH,shell 自然找不到命令。
解决方案是手动把新 bin 目录加入 PATH:
$env:Path += ";$env:USERPROFILE\.openclaw\bin"这行只在当前会话生效。想永久生效,用setx或者在系统环境变量里追加。另外,升级完成后建议重新开启一个 PowerShell 窗口,让环境变量重新加载,而不是在旧窗口里硬试。
还有一个 Windows 特有的问题是 workspace 路径。OpenClaw 在 Windows 上的默认 workspace 路径是C:\Users\<用户名>\.openclaw\workspace。如果你的config.toml里手动配置了 workspace 路径,升级后如果旧路径不存在了,OpenClaw 可能会在日志里报workspace not found,然后在启动时自动创建一个空目录。这个时候,你的项目文件看起来就像"丢失"了一样,实际上只是换了位置。
排查方法:打开config.toml,看workspace字段指向哪里,再用文件管理器确认目录是否存在、里面是否有文件。如果文件还在,只是 OpenClaw 没找到,大概率是配置中的路径分隔符写错了——Windows 路径建议统一用正斜杠/,而不是反斜杠\,因为在 TOML 里反斜杠需要进行转义,写错了就解析不到正确路径。
5.2 Linux 常见问题:残留进程导致端口占用和日志双写
Linux 上升级 OpenClaw,最常见的坑是旧版进程没退出干净。升级脚本通常会把新版可执行文件替换掉,但已经在内存里运行的旧进程不会自动被杀死。如果你先停服务再升级,这个问题不存在;如果你直接覆盖文件然后openclaw命令重新拉起,就可能出现两个进程同时跑的情况。
排查方法:
ps aux | grep -i openclaw如果看到两个以上进程,且启动时间不同,说明有残留进程。用kill <PID>逐个停掉旧进程,再重启新服务。
还有一个容易被忽略的问题:如果你用的是 systemd 管理 OpenClaw 服务,升级后 systemd 单元文件里的可执行路径可能已经失效。旧版如果安装在了/usr/local/bin/openclaw,新版可能改到了/opt/openclaw/bin/openclaw。这时候 systemd 服务启动会失败,但错误信息可能很笼统,比如code=exited, status=1/FAILURE。排查方式是systemctl status openclaw,查看输出里的 executable 路径,和which openclaw的结果对比一下,不一致就手动更新单元文件。
5.3 环境变量和 model 配置的共享坑
升级后另一个高频问题跟模型配置相关。v2026.3.22 引入了对 NVIDIA NIM 的配置支持,这也导致了一些兼容性问题——如果你之前用的是 OpenAI 兼容接口,升级后配置格式变了,模型加载会失败。
OpenClaw 在升级时会保留你原有的OPENAI_API_KEY这类环境变量,但如果你配置了多个模型提供商,升级后的配置结构变化可能让你指定的 model 名称失效。我的建议是升级后用openclaw model list重新确认一下模型列表,如果有模型标红或者缺失,手动修改 config 里的[models.xxx]段,把 provider、base_url、model_name 三个字段补全。不要依赖旧版本的配置自动迁移,模型提供商相关配置是最容易迁移出错的区域。
6. 这类升级排障的正确姿势:我的固定排查链路与处理顺序
6.1 固定排查链路:不要一上来就改配置
经历了这两天的折腾,我总结出一套升级类问题的排查顺序,如果你也遇到类似的"升级后某某功能不对"的情况,可以按这个顺序走:
第一步,确认版本和进程状态。执行openclaw --version、ps aux | grep -i openclaw(Windows 用任务管理器),确保新版本确实在运行,且只有一个主进程。
第二步,看日志。OpenClaw 的日志目录按日期分了文件,先看当天的runtime.log,重点关注WARN和ERROR级别的内容。不要只盯着最后一屏,用 grep 过滤关键词,比如feishu、ui、migrate、error。
第三步,跑体检。openclaw doctor这个命令会检查配置文件、插件加载、模型连接、网络连通性等。它的输出是分段的,可以比较直观地看到哪一块标红。
第四步,比对旧配置。如果你升级前备份了 config.toml,用 diff 工具对比新生成的 config 和旧配置,快速找出被改动的节点。很多时候问题就在配置迁移的差异里。
第五步,才轮到改配置。改完配置后,先openclaw config validate校验一次,再重启服务。不要在没有任何验证的情况下改完就重启,那样只会增加排查的复杂度。
6.2 容易混淆的错误信息分类
排障过程中,我注意到几个容易误导人的错误信息,在这里一起说明:
plugin loaded不代表插件配置正确。OpenClaw 的插件 loader 只负责加载插件二进制,不负责校验插件配置。要确认配置是否有效,看日志里有没有config invalid或using default字样。ui status显示端口正常,不代表浏览器一定能访问。如果监听地址是 IPv6 的::1,而浏览器输入的是 IPv4 的127.0.0.1,就会出现服务正常但你连不上的情况。exec-approvals.json的迁移提示不是错误。它只是一个提醒,告诉你旧格式的审批记录还在,不会影响 OpenClaw 本身的启动和运行。只有当你不迁移且依赖旧审批时,才会真正遇到问题。
6.3 最后的一点实战心得
这次升级让我印象最深的一点是:升级 OpenClaw 之后,不要急着跑复杂任务,先花十分钟把基础功能过一遍。具体路径是:先跑openclaw doctor看全局健康状态,再测试一个最简单的插件交互(比如给飞书机器人发条消息),最后打开 Control UI 确认页面能正常加载。这三步都通过了,再去处理你的自动化任务和项目文件,能省去"任务跑到一半发现插件失灵"这种最糟糕的情况。
另外,如果你和我一样常用多个环境(Windows 本机、Linux 服务器),建议给每个环境分别记录配置文件备份。不同平台上的 OpenClaw 服务配置迁移逻辑存在细微差异,用一套配置通吃所有环境,在 v2026.3.22 这个版本上依然不现实。分开维护,升级的时候一个一个确认,反而更快。