目录

OpenClaw 2026.9.2 → 2026.9.4 升级事故复盘:两个 JSON 文件引发的连锁排障

四个独立故障根因 + 一套可直接套用的稳定升级 SOP

OpenClaw 2026.9.2 → 2026.9.4 升级事故复盘:两个 JSON 文件引发的连锁排障

一次看似普通的 openclaw update,实际花了整整一个晚上加一个早晨才完成。这篇文章完整记录了排障全过程、四个独立的故障根因,以及最后总结出的稳定升级流程。适合所有自托管 OpenClaw、遇到 update 失败或 Gateway 起不来的用户。

背景

环境:

  • Ubuntu(systemd user service 部署)
  • Node 通过 nvm 安装(v24.16.0),系统另有 /usr/bin/node
  • OpenClaw 2026.9.2,npm 全局安装,Gateway 以 systemd user service 运行
  • 5 个飞书通道、200+ 个 agent 目录

症状:openclaw update 升级到 2026.9.4 时,openclaw doctor 阶段失败:

✗ openclaw doctor
  - Failed to migrate Skill Workshop proposal agnes-image-20260605-86fd8b3033:
    Error: proposal draft hash does not match proposal metadata
  - Failed to migrate Skill Workshop proposal agnes-video-20260605-e8839d11ff:
    Error: proposal draft hash does not match proposal metadata
Doctor stopped because a state migration refused to continue.

而且更糟的是,update 失败后 Gateway 直接起不来了。

事后看,这次事故其实是四个独立问题叠加:

  1. Skill Workshop 的遗留提案文件导致迁移拒绝
  2. 失败的 update 把主库 schema 迁移到一半
  3. 老旧的 systemd service unit 导致更新 handoff 失败
  4. 更新器 60 秒健康检查窗口对慢启动的 Gateway 太短(假警报)

下面按时间线逐一展开。

四故障根因时间线

第一个问题:迁移拒绝 —— 元凶不在数据库里

排查思路

报错说的是 “Skill Workshop proposal”,第一反应是查主状态库 ~/.openclaw/state/openclaw.sqlite。用 Python 遍历所有表搜 agnes:

import sqlite3
db = sqlite3.connect('/home/oklife/.openclaw/state/openclaw.sqlite')
tables = [r[0] for r in db.execute(
    "SELECT name FROM sqlite_master WHERE type='table'")]
for t in tables:
    for row in db.execute(f'SELECT * FROM "{t}"'):
        if 'agnes' in str(row):
            print(t, row)

结果:零命中。 数据库里根本没有 agnes。

那迁移器是从哪里读到这两个 proposal 的?换思路,直接全盘搜索文件系统(排除 node_modules,否则巨慢):

grep -rl "agnes-image-20260605" ~/.openclaw 2>/dev/null | grep -v node_modules
find ~/.openclaw -name "*.sqlite*" -not -path "*node_modules*" 2>/dev/null

结果定位到了真凶:

~/.openclaw/skill-workshop/proposals/agnes-image-20260605-86fd8b3033/proposal.json
~/.openclaw/skill-workshop/proposals/agnes-video-20260605-e8839d11ff/proposal.json

Skill Workshop 的提案是以 JSON 文件形式存在磁盘上的,迁移器读这些文件往数据库表里迁移。这两个 6 月份的提案(状态已是 rejected)文件里的 draftHash 和实际草稿文件对不上,迁移器直接拒绝继续,整个 update 卡死。

(grep 同时在一些 agent 的会话库和 media/inbound 里发现 agnes 字样,那些只是聊天记录文本,无害。)

关键教训

早前一次清理时,AI 助手只删除了数据库里的 proposal 记录行,没删磁盘上的提案目录,于是每次 update 都重新撞墙。对于"文件 + 数据库"双写的数据,清理时必须两头都清。

第二个问题:失败更新留下的半迁移 schema

删掉文件之前,先发现了更紧急的问题:update 失败后 Gateway 起不来了。

日志:

Gateway failed to start: SQLite schema is incomplete or noncanonical for
~/.openclaw/state/openclaw.sqlite
- column definitions differ for skill_workshop_collection_reviews
- missing or drifted index idx_skill_workshop_collection_reviews_workspace_time
- column definitions differ for skill_workshop_proposals
- column definitions differ for worker_environments

三张表处于新旧 schema 之间的中间态。

一个容易踩的坑:integrity_check 会骗人

python3 -c "import sqlite3; print(sqlite3.connect(
  '/home/oklife/.openclaw/state/openclaw.sqlite'
).execute('PRAGMA integrity_check;').fetchall())"
# 输出 [('ok',)]

integrity_check 返回 ok,但 Gateway 还是起不来。原因是 integrity_check 只检查页结构物理完整性,不校验 schema 是否符合应用预期。半迁移的库物理上是好的,逻辑上是坏的。

修复:还原备份

好在升级前做过备份(~/openclaw-backup-<时间戳>/state)。恢复流程:

# 1. 停掉起不来的服务
systemctl --user stop openclaw-gateway.service

# 2. 把坏库挪开留档,还原 pre-update 备份
mv ~/.openclaw/state ~/.openclaw/state-broken-$(date +%F-%H%M%S)
cp -av ~/openclaw-backup-2026-09-17-223335/state ~/.openclaw/state

# 3. 确认提案目录内容后删除(根治)
ls -la ~/.openclaw/skill-workshop/proposals/agnes-image-20260605-86fd8b3033/
rm -rf ~/.openclaw/skill-workshop/proposals/agnes-image-20260605-86fd8b3033
rm -rf ~/.openclaw/skill-workshop/proposals/agnes-video-20260605-e8839d11ff

# 4. 验证库里没有残留
grep -c "agnes" ~/.openclaw/state/openclaw.sqlite || echo "clean"

# 5. 重启验证
openclaw gateway start
sleep 120
openclaw gateway status   # Connectivity probe: ok ✓

Gateway 回到 2026.9.2 正常运行,agnes 隐患根除。

第三个问题:update handoff 失败 —— 老旧 service unit 的锅

以为万事大吉,重跑 openclaw update,结果连续两次死在同一处。

现象:update 走到 activating 阶段后卡住,最终 Gateway 处于 failed 状态(exit 9 / SIGKILL),端口没人监听。

更新器的 handoff 日志 /tmp/openclaw-update-run-handoff-*/handoff.log 给出了答案:

handoff failed: Error: systemd service remained active or changed execution generation
recovery refused: parked systemd service identity changed or stop is incomplete

配合 journalctl 看完整链条:

[gateway] received SIGTERM; shutting down
[gateway] draining active work before stop with timeout 315000ms: activeTasks=1
[gateway] still draining active work before stop: activeTasks=1   ← 每30秒刷一次
[gateway] active-work drain timeout reached; proceeding with shutdown
systemd: Main process exited, code=killed, status=9/KILL
systemd: Failed with result 'signal'

失败链条:Gateway 收到停止指令 → 有一个活跃任务(实测主要是 Brave 浏览器的 websocket 连接)不肯结束 → drain 等 5 分钟超时 → systemd SIGKILL 强杀 → handoff 脚本看到服务以 signal 状态退出,判定"停得不干净" → 拒绝恢复 → 更新回滚,Gateway 无人拉起。

systemd drain 失败链条

修复:重装 service unit

openclaw gateway status 一直有个提示:

Service config looks out of date or non-standard.
Service config issue: Gateway service PATH includes version managers...
Recommendation: reinstall with "openclaw gateway install --force"

老 unit 是早期安装生成的(PATH 里带 nvm 路径等非标准内容),handoff 的 “changed execution generation” 校验就是被它绊倒的。重装:

openclaw gateway install --force

输出确认:

Installed systemd service: ~/.config/systemd/user/openclaw-gateway.service
Previous unit backed up to: ...openclaw-gateway.service.bak

顺带一提,如果这一步报 SERVICE_DEFINITION_UNKNOWN: [unsafe-permissions],检查并修掉 ~/.config 目录链上的 group/world 写权限:

stat -c '%A %U %G %n' ~/.config ~/.config/systemd ~/.config/systemd/user
chmod go-w ~/.config ~/.config/systemd ~/.config/systemd/user

最终成功姿势:预先干净停服再更新

unit 修好后,采用"手动停服 → update"的姿势,绕开 handoff 的 drain/park 环节:

# 1. 先确认新 service 能正常跑
systemctl --user start openclaw-gateway.service
sleep 120
openclaw gateway status          # Connectivity probe: ok ✓
openclaw channels status --probe # 飞书 5/5 connected ✓

# 2. 备份(必须做)
openclaw backup create

# 3. 关掉连着 Gateway 的浏览器标签页(减少活跃任务)

# 4. 干净停服——注意 stop 可能阻塞 5 分钟,不要 Ctrl+C
systemctl --user stop openclaw-gateway.service
systemctl --user reset-failed openclaw-gateway.service
ss -tlnp | grep 18789 || echo "port free"

# 5. 更新
openclaw update

结果:

✓ global update (19.28s)
✓ openclaw doctor (123.21s)     ← 迁移全部通过!
Phase: restarting
Phase: verifying
⚠️ OpenClaw update failed: restart-unhealthy. The gateway is running 2026.9.4.

第四个问题(假警报):restart-unhealthy

最后这个 “failed” 把人吓一跳,但细看三行关键信息:

Gateway: restart failed: ... Gateway restart timed out after 60s waiting for health checks
Verification: gateway booted; service running; version verified.
⚠️ The gateway is running 2026.9.4.

更新实际成功了。 只是 Gateway 预热要两分钟左右,超过更新器 60 秒的健康检查窗口,触发了一个假警报。验证确认:

openclaw --version            # OpenClaw 2026.9.4 ✓
openclaw gateway status       # Gateway version 2026.9.4, Connectivity probe: ok ✓
openclaw channels status --probe  # 飞书 5/5 connected, works ✓
openclaw doctor --non-interactive # Doctor complete,无 error ✓

遇到 restart-unhealthy 先别慌,跑一遍上面四条命令看实际状态,很可能已经升级完成。

收尾:插件版本对齐

Gateway 升到 2026.9.4 后,20 个官方插件仍 pin 在 2026.9.2。完整的逐个解 pin 命令、第三方插件处理原则和最终重启验收,见下文「收尾:插件版本对齐与最终重启」。

11 步升级 SOP 流程图

总结:OpenClaw 稳定升级 SOP

# ── 升级前 ──
openclaw backup create                          # 1. 备份,永远的第一步
openclaw gateway status                         # 2. 确认当前状态健康
openclaw doctor --non-interactive               # 3. 体检,先解决 error 级问题
# 4. 关闭浏览器等长连接客户端

# ── 升级 ──
systemctl --user stop openclaw-gateway.service  # 5. 预先干净停服
systemctl --user reset-failed openclaw-gateway.service
ss -tlnp | grep 18789 || echo "port free"       # 6. 确认端口释放
openclaw update                                 # 7. 更新

# ── 验收 ──
openclaw --version                              # 8. 版本确认
openclaw gateway status                         # 9. 连通性确认
openclaw channels status --probe                # 10. 通道确认
openclaw doctor --non-interactive               # 11. 终检

五条核心教训

  1. integrity_check ok ≠ 库没问题。它只验物理完整性;应用层的 “schema noncanonical” 要靠 Gateway 启动日志判断。
  2. 迁移失败的数据源头可能不在数据库里。OpenClaw 的 Skill Workshop 提案是"磁盘 JSON 文件 + 数据库记录"双份的,排查时 grep -rl <关键词> ~/.openclaw | grep -v node_modules 比只查库有效。
  3. service unit 过期会以最诡异的方式炸更新。handoff 报 “changed execution generation” 时,先 openclaw gateway install --force 重装 unit。
  4. 预先手动停服是最稳的升级姿势。绕开 handoff 的 drain 等待,也就绕开了 “活跃任务 → drain 超时 → SIGKILL → handoff 拒绝恢复” 整条失败链。手动 stop 阻塞几分钟属正常,别 Ctrl+C。
  5. restart-unhealthy 可能是假警报。60 秒健康检查窗口对慢预热的实例太短,最终以 openclaw --version + gateway status 的实际状态为准。

附:关键路径速查

用途路径
主状态库~/.openclaw/state/openclaw.sqlite
Skill Workshop 提案~/.openclaw/skill-workshop/proposals/<id>/proposal.json
更新 handoff 日志/tmp/openclaw-update-run-handoff-*/handoff.log
Gateway 日志journalctl --user -u openclaw-gateway.service
运行日志/tmp/openclaw/openclaw-YYYY-MM-DD.log
Triage 提示词~/.openclaw/logs/support/openclaw-triage-prompt-*.md
备份归档~/YYYY-MM-DDT...-openclaw-backup.tar.gz

收尾:插件版本对齐与最终重启

openclaw update 只把主程序升到 2026.9.4,不会自动解开官方插件的兼容 pin(doctor 会提示 20 active official plugins not on post-restart 2026.9.4)。完整步骤如下。

官方插件逐个解 pin

对官方插件要写目标版本,不能写成当前版本:

openclaw plugins update @openclaw/acpx@2026.9.4
openclaw plugins update @openclaw/cerebras-provider@2026.9.4
openclaw plugins update @openclaw/cloudflare-ai-gateway-provider@2026.9.4
openclaw plugins update @openclaw/comfy-provider@2026.9.4
openclaw plugins update @openclaw/exa-plugin@2026.9.4
openclaw plugins update @openclaw/feishu@2026.9.4
openclaw plugins update @openclaw/firecrawl-plugin@2026.9.4
openclaw plugins update @openclaw/gradium-speech@2026.9.4
openclaw plugins update @openclaw/inworld-speech@2026.9.4
openclaw plugins update @openclaw/llama-cpp-provider@2026.9.4
openclaw plugins update @openclaw/longcat-provider@2026.9.4
openclaw plugins update @openclaw/openshell-sandbox@2026.9.4
openclaw plugins update @openclaw/qwen-provider@2026.9.4
openclaw plugins update @openclaw/stepfun-provider@2026.9.4
openclaw plugins update @openclaw/synthetic-provider@2026.9.4
openclaw plugins update @openclaw/tavily-plugin@2026.9.4
openclaw plugins update @openclaw/tokenjuice@2026.9.4
openclaw plugins update @openclaw/vercel-ai-gateway-provider@2026.9.4
openclaw plugins update @openclaw/voyage-provider@2026.9.4
openclaw plugins update @openclaw/zai-provider@2026.9.4

第三方插件单独判断

  • brave:如果被 pin 在旧版本,需要单独升到 @2026.9.4。
  • openclaw-weixin:属于第三方插件,不与官方 2026.9.4 对齐捆绑;如无明确需要,可保持现状。

原则:不顺手大面积升第三方插件,避免引入额外变量。

最终干净重启

插件更新完不代表运行时已加载,必须重启 Gateway:

systemctl --user stop openclaw-gateway.service
systemctl --user reset-failed openclaw-gateway.service
ss -tlnp | grep 18789 || echo "port free"

systemctl --user start openclaw-gateway.service
sleep 90
openclaw gateway status
openclaw channels status --probe

如果 systemctl --user stop 再次卡住,先查:

journalctl --user -u openclaw-gateway.service -n 40 --no-pager

看是否还是 drain / activeTasks / SIGKILL 这条链路。

最终验收标准

  • openclaw --version 显示 2026.9.4
  • openclaw gateway status 中 Gateway version 为 2026.9.4
  • Connectivity probe: ok
  • 飞书 5/5 connected, works
  • openclaw doctor --lint --json 不再提示官方插件版本漂移

回滚点

  • 升级前 fresh backup
  • 上一稳定版:2026.9.2
  • 本次变更边界:主程序 2026.9.4 + 官方插件对齐 2026.9.4 + 个别第三方插件按需更新

环境:OpenClaw 2026.9.2 → 2026.9.4,Ubuntu + systemd user service,npm 安装。写于 2026-09-18。


关联阅读

  • [[openclaw-2026-9-2-upgrade-troubleshooting]]
  • [[openclaw-gateway-v8-gc-restart-loop]]

参考来源