目录

memory_search 突然变弱?一次 WSL 9p 协议 Bug 引发的血案

qmd 进程因 EIO 崩溃,OpenClaw 自动 fallback 到本地小模型——排查全过程复盘

memory_search 突然变弱?一次 WSL 9p 协议 Bug 引发的血案

本文更新于 2026-07-04。原始排查记录归档于 2026-05-17。

前言:一场悄无声息的降级

2026 年 5 月 16 日至 17 日,oc-engineer agent 的 memory_search 功能出现了一个诡异的现象——语义搜索质量突然大幅下降,但没有任何人主动修改过配置。

Gateway 日志里满是 unable to open database file 的错误,系统自动 fallback 到了内置的本地引擎(sentence-transformers/all-MiniLM-L6-v2)。这意味着原本强大的向量搜索 + reranking 被降级为本地小模型,搜索精度直线下降。

这就像你突然发现手机导航变慢了——功能还在,但体验已经天差地别。

错误链路还原:从 EIO 到全链路崩溃

问题的完整链条比想象中复杂得多:

1. Gateway 启动 → 触发 qmd session-start sync
2. qmd 递归扫描配置的 22 个 collection 路径
3. 扫描到 /mnt/g/.../AI/05-智能体 目录时
4. WSL 9p 协议层 scandir() 返回 EIO (I/O error)
5. qmd 进程以 exit code 1 crash
6. OpenClaw 捕获错误,报 "unable to open database file"
7. memory_search 自动 fallback 到 builtin 本地引擎
8. 搜索质量从 qmd 向量搜索降级为本地小模型

关键点在于:真正的根因根本不是数据库文件本身有问题。而是 WSL 的 9p 协议层在扫描特定目录时触发了 I/O 错误,导致 qmd 进程崩溃。

./illustrations/1.webp

为什么这么难排查?

如果你亲自参与过这次排查,就会知道它有多折磨人。我们尝试了整整六种方案,每一种都看似合理却全部失败:

尝试方案预期结果实际结果教训
在 qmd paths 加 ignorePatterns跳过问题目录配置校验失败,非 qmd schema不要瞎加不支持的字段
umount/remount /mnt/g刷新 9p 缓存Protocol not availableWSL 内核 9p 是内建的
chkdsk G: /f修复文件系统无问题问题不在 Windows 文件系统层
目录剪切到桌面再粘贴回重建目录元数据inode 不变,EIO 依旧WSL 9p 缓存了旧句柄
wsl –shutdown 重启清除所有缓存问题依旧9p 缓存在 WSL VM 内部
修改 qmd index.yml 加 exclude排除问题目录qmd 不支持 exclude 字段先查 schema 再修改

每一种方案的失败都指向同一个事实:问题不在用户空间,而在 WSL 内核层的 9p 协议实现中

问题目录的技术特征

为了确认根因,我们对问题目录做了一系列技术检查:

检查项结果含义
Windows chkdsk G: /f无问题NTFS 文件系统层完好
WSL ls 目录能列出文件名,exit code 2readdir 返回 EIO
WSL stat 目录内文件全部正常文件本身可访问
WSL mkdir/rmdir 子目录正常目录写权限正常
WSL inode 号重启前后不变9p 缓存了旧句柄
WSL 重启 (wsl –shutdown)问题依旧缓存在 WSL VM 内核层

这些检查结果勾勒出了一个清晰的画像:Windows 侧的文件系统完好无损,问题出在 WSL 与 Windows 之间的 9p 协议层

真正有效的修复步骤

在排除了所有错误方向之后,最终的修复方案出奇地简单:

  1. 在 Windows 资源管理器中将 05-智能体 目录剪切到桌面再粘贴回原位置(并重命名为 05-agent 智能体
  2. 执行 wsl --shutdown 完全重启 WSL
  3. 手动修复被污染的 openclaw.json 配置(移除之前瞎加的 ignorePatterns 字段)
  4. 执行 openclaw gateway restart 重启 gateway
  5. 验证 openclaw config validate 通过

重启后,memory_search 恢复正常,qmd provider 正常工作,不再 fallback 到 builtin。

./illustrations/2.webp

根因深度分析

WSL 9p 协议层 Bug

WSL 的 9p 协议是 Linux 内核与 Windows 文件系统之间的桥梁。某些目录状态变化(删除子目录、权限变更、元数据修改等)会导致 9p server 在 readdir 系统调用时返回 EIO,即使 Windows 侧目录元数据完好无损。

这是一个 WSL2 内核与 Windows 9p server 之间的协议层问题,用户空间无法修复。

OpenClaw 错误处理过于激进

qmd session-start sync 失败后,OpenClaw 直接报 "unable to open database file",这个错误信息具有严重误导性,让排查方向偏离到数据库文件本身,而不是 qmd 进程 crash 的真正原因。

qmd + WSL + Windows 9p 是不稳定组合

qmd 依赖递归扫描文件系统建立索引,而 WSL 的 9p 协议在目录元数据缓存方面存在已知限制,两者结合容易触发 EIO 错误。

生产环境建议

基于这次排查的经验,我给出三个递进式的解决方案:

方案 A(强烈推荐):迁移到 WSL 原生文件系统

将 Obsidian vault 迁移到 WSL 原生文件系统(如 ~/obsidian-vault),完全避免 9p 协议层问题。性能更好,稳定性更高。

方案 B(妥协方案):改回 builtin 引擎

如果必须使用 Windows 盘挂载,将 memory.backend 改回 "builtin",牺牲搜索质量换取稳定性。builtin 引擎不依赖外部进程,不会触发 session-start sync。

方案 C(监控方案):添加 EIO 错误检测

如果坚持用 qmd + 9p 组合,添加监控脚本检测 qmd session-start 日志中的 EIO 错误,发现后立即告警并定位问题目录。

经验教训

这次排查给我上了好几课:

第一,优先验证数据库本身。 一开始就应该用 sqlite3 直接打开所有相关数据库文件验证完整性和权限,而不是绕弯子查目录权限、9p 缓存、文件系统损坏等外围问题。

第二,9p 缓存无法在用户空间清除。 WSL 的 9p 缓存在内核/VM 层,wsl --shutdown 不一定能刷新,需要完全重启 WSL VM 或等待微软修复内核 bug。

第三,不要瞎改配置。 添加不支持的 schema 字段(如 ignorePatterns)只会污染配置文件,增加后续修复成本。修改配置前必须先查 schema 定义。

第四,错误日志要完整捕获。 Gateway 日志会被新日志快速冲刷,关键错误要在出现时立即捕获保存,否则后续排查缺乏依据。

第五,session 上下文限制要注意。 排查期间 oc-engineer 子会话 cb2b3da0 因输入超过 131072 tokens 而 failed,长会话需要定期归档或重置上下文。

后续行动

  • 检查其他 21 个 collection 路径是否存在类似 EIO 风险(特别是 /mnt/g//mnt/j/ 挂载路径)
  • 评估将 AI vault 迁移到 WSL 原生文件系统的工作量和风险
  • 在 OpenClaw GitHub 社区反馈 qmd session-start 错误信息不够明确的问题
  • 建立定期归档机制,避免子会话上下文超过 131072 tokens 上限

归档自 agent-ops 与风哥的排查会话 | Session: 50712bc2-bcf3-4ac8-b715-eedc7f8a08ca | 原始归档时间:2026-05-17 18:02


–全文完–

感谢阅读
若你有故事想讲、有困惑想聊、或是想找个人说说心里话,甚至只是吐槽发泄一下情绪,都欢迎来找我聊聊:   《内容已折叠,点击展开》

希望我写的每一个字,成为我自己和某个人活下去、拼下去的力量。                     《内容已折叠,点击展开》

“技术终归是工具,而我们一次次认真把问题理顺,守住的其实不只是页面样式和代码输出,还有那一点不愿被混乱打败的心气,是每一个深夜仍愿点灯前行的人。”

转载请注明来自https://oklife.me。

文尾配图水墨画图片