OpenClaw 从 9.6 降级到 7.35:插件版本不匹配与 SQLite 不兼容的处理记录

背景

9 月 26 日晚上,我把 OpenClaw 从 2026.9.6 降级到 2026.7.35。

起因是性能。9.6 上线后,网关内存常态性顶到 1.5 GiB 的警戒线,会话列表偶发两秒多的慢查询,微信、WebChat、控制台的响应都明显变慢。这不是个例:上游 issue #155191 报告 9.5 起存在 native 内存泄漏,至今未关闭;#157791 报告 9.6 启动后 RSS 快速冲破 1.5 GiB;而 9.6 的 release notes 里没有任何内存或性能修复条目——等热修没有明确时间表。

权衡之后选择退回 7.x LTS 线,先保证稳定,等上游修复性能问题再考虑升级。

升级的文章很多,降级的很少。但降级的风险高于升级:升级有官方迁移脚本兜底,降级则要面对「新版本写入的数据、旧版本无法识别」的问题。这次实际遇到两个,以下分别记录。

问题一:插件与运行时版本不匹配

现象

切换到 7.35 并启动后,网关正常运行,但 tavily(搜索)、deepseek、volcengine(火山)三个插件全部异常,对应功能不可用。

原因

这三个插件安装于 9.x 时期,代码依赖 9.x 的运行时 API。降级后运行时回到 7 月版本,插件仍为 9 月版本,接口签名对不上,加载即失败。

该问题的实际影响大于后续的 SQLite 问题,因为它是显性的:功能当场失效,且报错位置分散。排查期间,部分错误表现为某个模型渠道返回 400/401,极易误导方向——实际上需要检查的是订阅状态和端点配置,与插件无关的错误会消耗大量时间。

处理步骤

处理原则是卸载干净后重装,不做就地升级——版本跨度较大时,就地升级的可靠性不足。

这里有一个前提要先说清楚:网关起不来的状态下,openclaw plugins 系列命令不可用。这些命令需要与运行时交互(升级期间就出现过 plugins update 报 runtime application failed 的情况),运行时本身是坏的,命令自然跟着失败。所以修复分两个阶段:网关起不来时用离线手段处理,网关恢复后再用 CLI 重装。

阶段一:网关起不来(离线处理)

第一步:直接编辑配置,禁用问题插件。

不经过任何 OpenClaw 命令,用编辑器打开 ~/.openclaw/openclaw.json,找到 plugins.entries 段(本例有 32 个条目),把出问题的插件改为 false:

"plugins": {
  "entries": {
    "deepseek": { "enabled": false },
    "volcengine": { "enabled": false },
    "tavily": { "enabled": false }
  }
}

找不到对应条目就直接新增,改完确认 JSON 语法合法(python3 -m json.tool < openclaw.json 可以快速校验)。

第二步:手动清理已安装插件的残留。

独立安装的插件存放在 ~/.openclaw/npm/projects/ 目录,目录名带 hash 后缀:

ls ~/.openclaw/npm/projects/
# 例如:openclaw-deepseek-provider-2481ed984b

直接删除(或改名加后缀,保留可恢复性)目标插件目录。本次实际操作就是改名隔离,目录至今保留着 .bak96-20260927014540 后缀:

mv ~/.openclaw/npm/projects/openclaw-deepseek-provider-2481ed984b{,.bak}

注意:目录名与插件 ID 不一定完全对应(如 volcengine 的目录名含生成流水号),用 hash 或关键词模糊匹配即可。内置(stock)插件不在这个目录,只需第一步的配置禁用。

第三步:启动网关并核对。

openclaw status          # 确认网关能正常启动
openclaw plugins list    # 确认目标插件已消失,或 Status 为 disabled

阶段二:网关恢复后(CLI 重装)

第四步:用 CLI 重装匹配版本的插件。

此时运行时已恢复正常,plugins 命令可用:

openclaw plugins install <插件规格>   # npm 包名 / 路径 / git 仓库 / clawhub: 包
openclaw plugins enable deepseek      # 配置中重新启用
openclaw plugins list                 # 核对 Version 已更新、Status 为 enabled

若安装过程中报错,用 openclaw plugins doctor 查看加载失败原因。

步骤顺序不可调换。若不先清理残留,新安装的版本可能被旧文件覆盖,出现「装了但仍是旧版」的情况,这类问题排查成本很高;若不先禁用即启动,失败的插件会干扰启动过程,使错误来源难以区分。

小结

问题二:SQLite 跨版本不兼容

三层不兼容

9.6 与 7.35 之间存在存储架构差异:9.6 将会话历史写入 openclaw-agent.sqlite;7.35 的会话存储为 sessions.json 加 jsonl 转录文件,源码中不读取该 sqlite 库。

实测不兼容分三层,严重程度依次递增:

  1. state 库:user_version 为 18,7.35 支持 1。启动时报 uses newer schema version 错误,但进程不退出,status 可正常输出;
  2. agent 会话库:schema 版本 23,7.35 直接跳过读取。sessions list 返回空,38 个会话静默消失——无报错、无崩溃。此类静默失效若不主动验证,难以发现;
  3. 启动检测:网关启动时被主动拦截,报错 Refusing to run automatic gateway startup migrations because this binary is older than the config last written by ...。7.35 内置降级检测,需设置 OPENCLAW_ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS=1 方可继续。

为何放弃「导出再导入」

初始方案是将旧库会话导出,再导入新版本。调研后放弃,原因有二。

其一,工具不匹配。9.6 的 sessions export-trajectory 导出的是脱敏轨迹,不是可还原的会话数据;而 7.35 没有对应的导入目标——它的会话存储根本不是 sqlite,导出数据无处可放。

其二,价值排序。跨版本数据搬运的风险与工作量都不小,而数据分两类:会话历史属于过程记录,MEMORY.md 与 memory/*.md 下的记忆文件才是持续使用的资产。前者可放弃,后者必须完整迁移。

实际方案

  1. 旧会话原样保留:完整备份 sqlite 库(含 38 个会话),7.35 不读取即不读取,将来回到 9.x 仍可找回;
  2. 记忆文件直接迁移:MEMORY.md、memory/*.md 等纯文本 rsync 到新环境,执行 openclaw memory index 重建向量索引。实测 93 个文件、1668 个 chunk,耗时约两个半小时,期间系统正常使用,仅记忆检索暂时不可用;
  3. 配置字段转换:生产配置中 6 处字段 7.35 不识别(meta.migrations、ui.prefs、modelPolicy 与 fastModeDefault、controlUi.sessionObserver、memory.search 需迁移为 agents.defaults.memorySearch、agents.entries 需改为 agents.list 数组结构),逐项修剪后通过 config validate。

小结

两个附带发现

配置存在双源。 openclaw.json 是配置源头,agents/<id>/agent/models.json 是运行时派生文件,两者可能不一致。排查模型渠道报错时曾耗时数小时,最终定位为派生文件中 provider 级 baseUrl 仍指向已废弃端点——修改源头文件不会立即生效,需重启使运行时重新生成。排查模型配置问题时,两个文件需同时核对。

MCP 服务器为网关级单实例。 所有会话共享同一进程,并非每会话独立。本次遇到两例:其一,MCP 服务器可执行文件目录被整体删除,报 write EPIPE,重装后恢复;其二,设备码授权在命令行侧完成、token 已写入缓存后,网关侧进程仍持有旧的 pending 状态,mcp reload 不生效,需终止进程强制重建连接。

结语

降级至 7.35 后运行稳定,性能问题消失。代价同样明确:会话历史暂不可读、配置做了 6 处裁剪、三个插件重装。

流程上,本次正确的是先备份(配置、数据库、镜像三件套)再操作,以及用配置变体二分法预检兼容性;不足在于未提前核查插件兼容性,使其成为耗时最长的问题。

下次若再执行降级,检查清单应为五项:镜像是否存在、schema 是否兼容、插件是否对版、配置能否通过 validate、备份是否完整。五项全部确认后再动手。

← 返回文章列表