给 C:\codes\zhimalab 跑 index this project(codebase-memory-mcp 全量索引),接口只回一句笼统的失败,真实原因完全看不到。前后排查了很久,最后发现根因竟是一个 85 字节、从未进过 git 的杂散文件 nul 。这篇记的不是"怎么索引",而是为什么一个通用报错会让人绕这么大一圈。
症状:一句无法定位的报错
text
{"project":"C-codes-zhimalab","status":"error",
"hint":"Pipeline failed. Check repo_path exists and contains source files."}
"路径不存在 / 没有源文件"?仓库明明在、src/ 下有 1265 个文件。这句提示是个兜底文案 ------所有管线错误都长这样,真实错误被吞掉了。CBM_LOG_LEVEL=trace、CBM_INDEX_LOG、CBM_LSP_DISABLED 轮番试过,细节始终没浮出水面(worker 进程 clean exit 0,日志里也只有这句通用错误)。
排查:绕了两个弯路
弯路一:怀疑损坏的缓存目录
当前会话的 cbm daemon 跑在一条损坏的缓存树 C:\c\Users\peini\.cache\codebase-memory-mcp 上(早前一次 --dir 参数损坏的安装残留),正式缓存里 zhimalab.db 主文件还丢了。第一反应就是它。但同一缓存里 olympic 能正常索引 → 排除。
弯路二:C:\tmp 的 DACL 干扰
为复现,我在 C:\tmp 建了最小 TS 仓库和最小 Python 仓库,全失败 ,一度得出"新项目一律失败、只有已索引的走增量能成功"的错误结论。直到把测试仓库放到 C:\codes 下、两个都一次成功,才意识到:C:\tmp 目录 DACL 不达标,测试仓库放那里会被 cache-private 校验直接拒掉,跟要查的问题毫无关系。
真正的隔离:干净 clone + 二分
关键一步是把仓库 git clone 到干净路径(避开 C:\tmp,放到 C:\codes 下)再索引:
- 已提交内容(clean clone)→ 成功(7817 nodes)→ 问题不在仓库已提交的东西;
- 逐个把工作区差异加回 clone:改过的
.cbmignore→ 成功;staged rename → 成功; - 把根目录四个杂散文件(
nul、{G.difficulty、{G.topic、tmpclaude-c878-cwd)加回去 → 失败; - 逐个二分 → 只有
nul会触发失败,其它三个无害。
根因:Windows 保留设备名
nul 是 Windows 保留设备名 (和 con、prn、aux 一样)。索引器按路径 open("C:/codes/zhimalab/nul") 时,Windows 把它当作空设备而不是普通文件,管线读取出错 → 整个索引整体失败。
更坑的是 .cbmignore 里明明写了 nul 排除规则也挡不住------文件枚举/打开发生在 ignore 过滤之前,等规则生效时管线已经炸了。而错误又恰好被包装成"仓库里没有源文件",于是百思不得其解。
文件内容是一段某次 ls 报错被重定向误捕获的痕迹:
yaml
ls: cannot access 'C:codeszhimalabsrccomponentstutorials': No such file or directory
纯属意外产生的垃圾文件,且未纳入 git。
解决
bash
rm -f nul # 删除杂散文件
重跑全量索引:27 秒完成,13,624 nodes / 45,794 edges,status: ready。
复盘:以后再遇到怎么快速搞定
- 别信那个通用提示的字面意思。"repo_path exists and contains source files" 是兜底文案,真实错误被工具吞了;
- 第一件事扫保留设备名 :
ls -la看根目录有没有nul/con/prn/aux/com1这类文件,有就删------这是 Windows 下索引失败的头号已知坑; - 测试仓库别放
C:\tmp:它的 DACL 不达标,永远会制造"新项目失败"的假象,放C:\codes或用户主目录; - 最快的隔离法是
git clone到干净路径:一步区分"已提交内容"还是"工作区状态",别再对着日志瞎猜; - 优先怀疑未跟踪的杂散文件:它们不在 git 里最容易漏,这次元凶正是它;
CBM_LOG_LEVEL/CBM_INDEX_LOG/CBM_LSP_DISABLED这组环境变量救不了这种错误,别浪费时间。
最后给个建议:把"索引前先扫杂散文件"做成一行小脚本(扫描 + 删除 + 执行 index),以后跑 index this project 就是一句命令的事。这个仓库已经落地了 cbm-index.sh,先扫并删保留设备名杂散文件再执行索引,还内置了对后台 watch 自动索引并发冲突的重试。注意一个实现细节:这类逐文件扫描必须用纯 bash 内建(${f##*/}、case),逐文件 $(basename)/grep 在 Git Bash 下跑几百次就会子进程累积卡死。