OpenClaw 的版本升级表面上只是更新一个 npm 包,但当实例已经积累了大量会话、状态数据库、插件和运行时数据后,真正困难的部分往往不是“把新版本装上去”,而是如何让旧状态安全迁移到新版本,并确认整个实例仍然属于标准、可继续升级的安装形态。

下面记录一次从 OpenClaw 2026.9.3 升级到 2026.9.5 的完整实例升级过程。内容仅涉及升级本身,包括更新失败、手工安装、数据库迁移、插件同步、安装形态验证以及升级后的启动验证。


一、升级前状态

目标实例运行于 ARM64 Linux 环境,OpenClaw 原版本为:

OpenClaw 2026.9.3

安装方式属于标准 npm 全局 package 安装,核心程序位于系统级 Node.js 全局模块目录中,由 systemd user service 管理 Gateway。

实例已经长期运行,包含:

  • 多个 Agent
  • 大量历史 Sessions
  • SQLite 状态数据库
  • 外部插件
  • 自定义 Workspace
  • systemd Gateway 服务

这意味着升级不能简单地只观察:

openclaw --version

真正需要确认的是:

程序版本
数据库 Schema
插件版本
状态迁移
Gateway
Agent
Sessions
未来 updater

全部能够同时正常工作。


二、官方 updater 再次卡在数据库预检

首先使用标准升级入口:

openclaw update

但升级没有进入真正的软件包替换阶段,而是停止在:

database-schema-preflight

核心错误是 SQLite 只读快照操作超过约 30 秒:

SQLite read-only snapshot timed out after 30 seconds

最初容易怀疑是 Gateway 正在占用数据库。

因此停止 Gateway,并确认相关数据库没有其他明显使用者后重新运行 updater。

结果没有变化。

这说明问题并不是简单的:

Gateway 正在运行
→ 数据库锁住
→ updater 无法检查

而更接近:

旧版 updater
    ↓
数据库升级前预检
    ↓
只读 SQLite snapshot
    ↓
在当前实例规模和存储性能下超过固定超时时间
    ↓
整个更新被阻止

这种失败有一个重要特点:

OpenClaw 本身仍然可以正常运行,但 updater 在真正开始更新之前就已经退出。

因此,继续重复执行同一个 updater 并不会带来新的结果。


三、改用标准 npm 包直接安装 2026.9.5

既然实例本身就是 npm package 安装,下一步直接使用 npm 替换全局 OpenClaw 软件包:

/usr/bin/npm i -g openclaw@2026.9.5 --allow-scripts=openclaw

安装成功后,版本由:

OpenClaw 2026.9.3

变为:

OpenClaw 2026.9.5

这一步说明:

2026.9.5 的程序文件已经成功安装。

但这还不能等同于:

OpenClaw 实例已经升级完成。

因为程序文件和运行数据是两件不同的事情。

此时旧实例的 SQLite 数据仍然可能保持旧 Schema。


四、程序升级成功,但数据库仍然属于旧版本

安装 2026.9.5 后进行只读检查,发现 Agent 数据库仍然需要升级。

实例中两个主要 Agent SQLite 数据库当时仍然处于:

schema version 19

而 2026.9.5 需要的新状态格式已经进入:

schema version 21

因此出现了典型的升级中间态:

OpenClaw binary = 2026.9.5

但

OpenClaw data schema = older version

这个状态不能直接当成完成。


五、使用 Doctor 完成数据库正式迁移

在 Gateway 停止状态下运行:

OPENCLAW_SERVICE_REPAIR_POLICY=external openclaw doctor --fix

这里使用:

OPENCLAW_SERVICE_REPAIR_POLICY=external

目的是让 Doctor 处理实例数据和迁移,而不擅自接管外部已有的服务管理方式。

迁移过程并不快。

期间能够观察到:

  • SQLite validation
  • Agent DB open
  • Session SQLite migration
  • delayed state migration
  • canonical validation
  • index validation
  • transaction lock wait

部分步骤耗时达到数秒甚至更长。

但最终两个 Agent 数据库都成功完成:

v19 → v21

这一步才真正完成了:

2026.9.3 数据状态
        ↓
2026.9.5 数据状态

的结构迁移。


六、确认 Session SQLite 已经没有遗留迁移项

数据库 Schema 升级完成后,继续运行 Session SQLite dry-run:

openclaw doctor \
  --session-sqlite dry-run \
  --session-sqlite-all-agents

最终返回:

0 target(s)
0 legacy entries
0 sqlite entries
0 issue(s)

这组结果非常重要。

它意味着当前已经不存在:

  • 等待迁移的 legacy session
  • 尚未完成的 SQLite session conversion
  • 明确的 Session SQLite 异常项

因此数据库迁移可以视为真正完成,而不是“版本号已经改成 v21,但后台还留着迁移任务”。


七、处理插件版本漂移

程序和数据库完成升级后,Doctor 继续发现若干插件存在版本漂移:

installed: 2026.9.3
expected: 2026.9.5

这类情况并不奇怪。

OpenClaw 核心程序升级并不意味着所有独立插件都会自动同步到同一个版本。

因此分别对受影响插件执行更新。

典型形式为:

openclaw plugins update <plugin>

完成后,核心插件和外部插件统一进入 2026.9.5 兼容状态。

后续状态检查显示:

Plugin compatibility: none

也就是没有留下已知插件兼容性冲突。


八、一个关键问题:手工 npm 安装会不会破坏以后正常升级?

手工执行:

npm i -g openclaw@2026.9.5

以后,一个非常重要的问题是:

OpenClaw updater 还能否把这个实例识别成正常安装?

如果 updater 不再知道当前软件包由谁管理,那么虽然眼前能运行,未来每次升级都可能只能继续手工处理。

因此专门检查了安装形态。


1. CLI 仍然指向标准 npm 全局包

OpenClaw CLI 仍然通过系统标准入口调用全局 npm package。

结构类似:

system binary
    ↓
global node_modules
    ↓
openclaw package

没有出现:

  • 自定义 wrapper
  • 临时目录启动
  • Git checkout 启动
  • 手工复制 dist
  • 非标准 launcher

2. npm 自己仍然识别这个包

执行全局包检查后,npm 能够正常看到:

openclaw@2026.9.5

也就是说:

npm package ownership 没有丢失。


3. OpenClaw updater 自己也识别为 package 安装

运行:

openclaw update status --json

能够看到类似:

installKind: package
packageManager: npm
channel: stable

这说明 OpenClaw 自己也没有把当前实例识别为未知来源。


九、最重要的验证:执行 updater dry-run

随后执行:

openclaw update --dry-run --json

这一步并不真正更新,而是让 updater 完整规划:

如果未来有新版本,现在这个实例会怎么升级?

dry-run 成功完成,并识别出:

currentVersion: 2026.9.5
targetVersion: 2026.9.5
installKind: package
mode: npm
updateInstallKind: package
effectiveChannel: stable
switchToGit: false
switchToPackage: false

这实际上证明了一个非常关键的结论:

直接通过 npm 安装 2026.9.5,并没有把实例变成“非官方安装”。

当前实例仍然属于:

standard npm package installation

以后仍然可以重新使用:

openclaw update

完成正常管理升级。


十、升级过程中暴露出的真正瓶颈:SQLite,而不是 npm

有意思的是,整个升级过程中最耗时间的并不是:

npm install

而是 SQLite。

多个阶段都出现了:

slow SQLite transaction
slow SQLite transaction lock wait
slow agent database open
slow canonical validation
slow session reclamation

部分 lock wait 达到数秒甚至十几秒。

一次 updater dry-run 本身就花费了数分钟。

这说明对于大型 OpenClaw 实例:

升级耗时往往取决于状态数据库,而不是程序包大小。

可以把升级过程抽象成:

安装代码
  ↓
打开状态数据库
  ↓
验证 Schema
  ↓
验证 Session
  ↓
建立/验证索引
  ↓
迁移状态
  ↓
插件同步
  ↓
启动 Gateway

越往后,SQLite 的影响越大。


十一、为什么 2026.9.5 能完成,而此前相近版本没有完成

此前曾对一个相邻版本尝试过相似的 npm 安装流程。

当时:

npm package replacement

本身也能完成,但后续:

database migration
startup validation
Gateway startup

没有最终进入稳定可用状态。

而 2026.9.5 在相同类型的机器、相同实例数据、相似存储环境下成功完成:

数据库迁移
Session validation
Gateway startup
运行验证

因此差异不能简单解释为:

“换了一种安装方法。”

真正发生变化的是目标版本本身。

换句话说:

npm installation

只负责替换程序。

真正决定一个 OpenClaw 实例能否完成升级的是:

目标版本对旧数据库的迁移能力
+
状态数据库容错
+
启动阶段的生命周期管理
+
超时策略

十二、升级后的第一次 Gateway 启动并不顺利

完成数据库和插件升级后启动 Gateway。

systemd 很快显示服务:

active

但这并不意味着 Gateway 已经真正可以接受连接。

随后客户端连接仍然出现:

ECONNREFUSED

查看启动日志后发现,Gateway 仍然处于初始化阶段。


十三、systemd active 不等于 Gateway ready

2026.9.5 的启动过程包含大量后台初始化。

典型顺序类似:

systemd starts process
        ↓
loading configuration
        ↓
resolving authentication
        ↓
spawn broker
        ↓
SQLite validation
        ↓
session reclamation
        ↓
starting HTTP server
        ↓
starting channels
        ↓
starting sidecars
        ↓
gateway ready

因此:

systemctl: active

只代表:

Node 主进程已经存在。

它并不代表:

HTTP server 已监听

更不代表:

整个 Gateway 已 ready

这也是升级验证时容易产生误判的地方。


十四、第一次启动出现 state-lifecycle contention

第一次完整启动过程中还出现过一次真正的启动失败:

StateDatabaseCoordinatorContentionError

错误信息指向:

another OpenClaw process owns state-lifecycle

随后 Gateway:

startup failed

systemd 记录主进程退出,并按照服务策略自动重新启动。

这个错误与普通的:

database is locked

不是完全同一类问题。

普通 SQLite lock contention 在此前多个阶段都可以:

wait
→ retry
→ recovered

而 state-lifecycle contention 属于 OpenClaw 自身数据库生命周期协调器检测到所有权冲突。


十五、第二次自动启动成功

systemd 自动重启后,第二轮启动最终完成。

启动过程大致表现为:

service started
      ↓
configuration loading
      ↓
authentication
      ↓
SQLite validation
      ↓
HTTP server
      ↓
channels and sidecars
      ↓
gateway ready

这一轮仍然很慢。

从 systemd 开始启动,到最终:

[gateway] ready

用了大约数分钟。

期间仍然出现:

slow SQLite reclamation
event loop delay
high event loop utilization

但这些问题最终没有导致第二次失败。

Gateway 成功进入:

http server listening
gateway ready

十六、最终实例状态验证

升级最终不是以:

npm install returned 0

作为成功标准。

而是以实际运行状态为标准。

最终普通状态检查显示:

OpenClaw 2026.9.5
Gateway reachable
Gateway service running
Agents loaded
Sessions loaded
Plugins compatible
Channels operational

其中能够正常读取:

  • Agent
  • Sessions
  • Model
  • Channel
  • Plugin
  • Gateway
  • systemd service

状态。

这意味着升级后的实例已经完整恢复运行。


十七、最终升级链路

整个升级过程可以压缩成:

OpenClaw 2026.9.3
        │
        ▼
openclaw update
        │
        └── database-schema-preflight timeout
                │
                ▼
        updater 无法继续
                │
                ▼
npm install openclaw@2026.9.5
                │
                ▼
程序升级到 2026.9.5
                │
                ▼
doctor --fix
                │
                ▼
Agent DB schema v19 → v21
                │
                ▼
Session SQLite validation
                │
                ▼
0 migration issues
                │
                ▼
插件同步到 2026.9.5
                │
                ▼
update status
                │
                ▼
仍识别为标准 npm package
                │
                ▼
update --dry-run
                │
                ▼
未来 updater 路径验证成功
                │
                ▼
Gateway startup
                │
                ├── 第一次 state-lifecycle contention
                │
                └── systemd 自动重启
                        │
                        ▼
                第二次启动完成
                        │
                        ▼
                  gateway ready
                        │
                        ▼
             OpenClaw 2026.9.5 可用

十八、这次升级最值得注意的几个技术点

1. “程序升级成功”和“实例升级成功”不是同一个概念

npm install success

只能证明程序包已经替换。

完整实例还必须验证:

DB Schema
Sessions
Plugins
Gateway
Agents
Updater

2. updater 失败并不意味着新版本本身无法运行

这次真正阻止标准 updater 的,是旧版本 updater 的:

database-schema-preflight

而不是 npm package 安装失败。

绕开旧 updater 后,新版自己的迁移工具反而可以成功处理数据库。


3. SQLite 是大型 Agent 实例升级中的核心组件

随着 Session 和状态数据增长,OpenClaw 已经越来越像:

一个以 SQLite 状态数据库为核心的长期运行服务

而不只是一个 Node.js CLI。

因此升级问题往往表现为:

database validation
transaction lock
schema migration
session reclamation
state lifecycle

而不是 JavaScript 文件本身。


4. 手工 npm 安装不一定破坏未来官方升级路径

只要仍然保持标准:

npm global package

结构,并且:

openclaw update status

仍然识别:

installKind = package
packageManager = npm

那么以后仍可以重新回到标准 updater。


5. systemd running 不等于应用已经 ready

对于初始化较重的服务:

systemd active

只能说明进程存活。

真正的应用健康状态应以:

socket listening
gateway ready
application status reachable

为准。


结语

这次 OpenClaw 2026.9.5 升级最终成功,但整个过程很好地展示了现代 Agent 平台升级与普通 CLI 软件更新之间的差异。

真正的升级对象已经不只是:

一个 npm package

而是一整套持续存在的运行状态:

程序
+
SQLite
+
Sessions
+
Agents
+
Plugins
+
Gateway
+
生命周期协调器

因此一个成熟的 OpenClaw 实例升级,更接近一次小型有状态服务迁移。

这次升级最终完成了:

2026.9.3
   ↓
2026.9.5

程序:完成
数据库:v19 → v21
Sessions:迁移检查通过
插件:同步
安装形态:保持标准 npm package
Updater:未来升级路径验证通过
Gateway:启动成功
实例:恢复正常运行

真正值得关注的并不是安装命令本身,而是程序更新之后,旧状态能否完整、安全地跨版本继续运行

Leave a Reply

Your email address will not be published. Required fields are marked *