首页
/ CodeGraph 故障排查完全指南:从"未初始化"到 `database is locked` 的六类常见问题与源码级解决方案

CodeGraph 故障排查完全指南:从"未初始化"到 `database is locked` 的六类常见问题与源码级解决方案

2026-09-06 15:16:45作者:毕习沙Eudora

CodeGraph 是一个预构建代码知识图谱工具,通过本地 SQLite 索引为 Claude Code、Codex、Gemini、Cursor 等 Agent 提供低开销的代码检索与探索能力,并随代码变更自动同步。本文基于官方故障排查文档,完整覆盖六个最高频问题的排查与修复路径——初始化缺失、索引缓慢、SQLite 锁竞争、MCP 连接失败、符号缺失、Windows/WSL 双环境共享检出——并结合 src/ 下的真实实现(连接 PRAGMA 配置、WAL 模式判定、CODEGRAPH_DIR 环境变量解析、文件监听降级逻辑)给出每一处结论的源码依据,帮助你定位问题时能直接读到对应的判定逻辑。

问题一:"CodeGraph not initialized"(未初始化)

症状:运行 codegraph 相关命令或 Agent 调用 MCP 工具时,提示 CodeGraph not initialized in <项目路径>

解决方法:先在项目目录下执行 codegraph init

这条错误信息并非简单文案,它来自明确的初始化判定逻辑。"已初始化"在 CodeGraph 中有严格定义,需要同时满足两个条件:

  1. 项目根目录下存在 .codegraph/ 目录;
  2. 该目录下存在 codegraph.db 数据库文件(仅有空目录不算初始化)。

这个判定实现在 isInitialized

export function isInitialized(projectRoot: string): boolean {
  const codegraphDir = getCodeGraphDir(projectRoot);
  if (!fs.existsSync(codegraphDir) || !fs.statSync(codegraphDir).isDirectory()) {
    return false;
  }
  // Must have codegraph.db, not just .codegraph folder
  const dbPath = path.join(codegraphDir, 'codegraph.db');
  return fs.existsSync(dbPath);
}

从源码结构看,当判定失败时,核心引擎会在 src/index.ts 中抛出 CodeGraph not initialized in <root>. Run init() first.;而 CLI 各子命令(indexsyncnodecontext 等)在 src/bin/codegraph.ts 中都会先做同样的检查并输出统一报错。此外还有两种衍生情况值得注意:

  • 误删了数据库文件:如果你曾手动删除 codegraph.db 但保留了 .codegraph/ 目录,init 会拒绝重复创建。此时删除整个 .codegraph 目录后重新 codegraph init 即可(错误提示中也会给出该建议,见 src/index.ts)。
  • 在子目录中运行:CodeGraph 会沿目录树向上查找最近的已初始化项目根(类似 git 找 .git),实现为 findNearestCodeGraphRoot。如果整个目录树都未初始化,报错才会出现——请确认你在项目目录内运行命令,或传入显式路径参数。

另外,MCP 工具层对未初始化项目有专门的"降级引导":当 Agent 调用工具时报 CodeGraph isn't available here — no .codegraph/ index exists,并附带提示 Agent 应改用自己的内置工具、由项目所有者决定是否执行 codegraph init(见 src/bin/codegraph.ts)。这是有意设计,避免 Agent 越权自动建索引。

问题二:索引速度慢

排查与优化手段(官方文档给出的两条核心建议):

  1. 确认大目录已被排除node_modules 等大目录只要被 gitignore 了就会被排除在索引之外。如果你的项目里出现未被 gitignore 的产物目录(生成代码、构建输出等),建议将其加入 .gitignore 或 CodeGraph 的排除配置。从源码结构看,子项目扫描本身就内置了一份"永不进入"的目录黑名单(node_modulesdistbuildtargetvendor.venv 等),定义在 SUBPROJECT_SCAN_SKIP
  2. 使用 --quiet 降低输出开销codegraph index 支持 -q, --quiet 选项以抑制进度输出(见 src/bin/codegraph.ts),在慢速终端或远程机器上可减少终端渲染带来的额外开销。

源码层面的补充说明:CodeGraph 的索引流水线本身已针对慢磁盘做过深度优化。以 WAL(写前日志)管理为例,src/db/wal-valve.ts 的文件头注释记录了实测数据:SQLite 默认的 wal_autocheckpoint 在批量索引时会把热 B-tree/FTS 页反复写回主库文件,占全部磁盘 I/O 的约 95%,在 HDD 级存储(约 150 随机 IOPS)上使索引耗时从 45 秒劣化到 19 分钟以上。为此 CodeGraph 在批量索引期间延迟自动 checkpoint,并引入"WAL 阀"机制:

  • 软阈值(默认 256 MB,可用 CODEGRAPH_WAL_VALVE_MB 覆盖,大项目按数据库体积自动放大到 dbSize/4 且上限 2 GB)触发工作线程上的 PRAGMA wal_checkpoint(PASSIVE) 回补;
  • 超过 2 倍软阈值的硬上限时,写入端会在事务间边界暂停,等待一次完整回补;
  • 可用 CODEGRAPH_WAL_VALVE_DEBUG=1 将阀门决策输出到 stderr 辅助诊断(见 WalCheckpointValve 构造函数)。

因此如果你观察到索引慢且磁盘 I/O 打满,可以先确认日志中是否有 [wal-valve] 的暂停记录,判断是磁盘追不上写入速度还是配置问题。

问题三:MCP 命中 database is locked

官方文档的结论是:当前版本不应该再出现这个问题。原因有二,均有源码直接佐证:

  1. 内置 Node 运行时 + node:sqlite:CodeGraph 发布版自带 Node 运行时,直接调用 Node 内置的真实 SQLite(node:sqlite,无 wasm 回退、无原生编译步骤),WAL 与 FTS5 全量可用。这一设计说明在 src/db/sqlite-adapter.ts 的模块注释中:"node:sqlite (real SQLite, with WAL + FTS5) is always available — there is no native build step and no wasm fallback."
  2. WAL 模式下并发读永不阻塞写者:每个连接建立时统一应用一组 PRAGMA(initializeopen 两条路径共享同一函数,防止行为漂移),见 configureConnection
function configureConnection(db: SqliteDatabase): void {
  db.pragma('busy_timeout = 5000');      // MUST be first — 先设超时的注释说明
  db.pragma('foreign_keys = ON');
  db.pragma('journal_mode = WAL');       // node:sqlite supports WAL on every platform
  db.pragma('synchronous = NORMAL');     // safe with WAL mode
  db.pragma('cache_size = -64000');      // 64 MB page cache
  db.pragma('temp_store = MEMORY');
  db.pragma('mmap_size = 268435456');   // 256 MB memory-mapped I/O
  db.pragma(`journal_size_limit = ${WAL_HEAL_THRESHOLD_BYTES}`);
}

注意 busy_timeout = 5000 被刻意放在最前面——注释解释了原因:如果打开数据库文件时另一个进程正持有写锁,先设置超时就让后续 PRAGMA 和首条查询"等锁"而不是立刻抛出 database is locked(对应 issue #238)。且 WAL 下读永远不阻塞写,该超时只管辖跨进程写竞争(例如 git hook 触发的 codegraph sync 与 MCP 服务写库同时进行)。

如果你仍然看到 database is locked,按文档排查两个方向:

  • 你用的是 0.9 之前的旧安装:旧版没有内置运行时,锁行为不可靠。重新安装即可获得内置运行时:

    • macOS/Linux:curl -fsSL https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh | sh
    • Windows:irm https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.ps1 | iex
    • npm i -g @colbymchenry/codegraph@latest
  • codegraph status 显示 Journal: 不是 wal:说明该文件系统上 WAL 无法生效(网络共享盘、WSL2 的 /mnt 挂载点常见),此时读会阻塞在写后面。解决办法:把项目(连同其 .codegraph/ 目录)移动到本地磁盘。

Journal: 这一行正是 codegraph status 中用来验证 WAL 是否生效的诊断字段,其渲染逻辑在 src/bin/codegraph.ts

const journalLabel = journalMode === 'wal'
  ? chalk.green('wal')
  : chalk.yellow(`${journalMode || 'unknown'} ${getGlyphs().dash} WAL inactive; reads can block on writes`);
console.log(`  Journal:   ${journalLabel}`);

源码注释进一步点明:node:sqlite 在所有平台都支持 WAL,所以非 wal 模式几乎总是"文件系统不支持"的信号(见 issue #238 的相关注释,位于同一文件的 L1072-L1075)。MCP 工具层同样会在响应中暴露该信息:当模式非 wal 时,工具输出会带 **Journal mode:** ⚠ … WAL not active, so reads can block on writes 的警告(见 src/mcp/tools.ts)。

问题四:MCP 服务器连不上

关键认知:MCP 服务器由你的 Agent(Claude Code、Cursor 等)自行拉起,不需要也不应该手动启动。排查顺序如下:

  1. 确认项目已初始化且已索引:运行 codegraph status,应能看到 Project:Index Statistics:(Files/Nodes/Edges/DB Size)等输出,而不是 Not initialized
  2. 核对 MCP 配置中的项目路径:配置里指向的路径必须是已初始化的项目根(或会被向上查找解析到的目录)。
  3. 重写配置:若路径正确仍连不上,重新运行 codegraph install,它会按你使用的 Agent 重写对应 MCP 配置。install 命令支持 --init 选项在同一步完成建索引(见 src/bin/codegraph.ts)。

从源码结构看,服务器侧有一套完整的守护与生命周期管理(src/mcp/ 下的 daemon-manager.tsdaemon-registry.tsdaemon-paths.tsliveness-watchdog.ts 等),文件监听与自动同步的启动会向日志输出 [CodeGraph MCP] File watcher active — graph will auto-sync on changes(见 src/mcp/engine.ts)。若你在 MCP 日志中看到监听已激活却仍"无响应",多半是配置路径解析到了错误的目录树;install 的各 Agent 适配器(src/installer/targets/)会针对每个客户端生成对应的配置写入方式,重跑一次是修复配置漂移最可靠的手段。

问题五:缺少符号(Missing symbols)

排查三步法

  1. 等待自动同步。MCP 服务器内置文件监听,保存文件后会触发自动同步(见 src/mcp/engine.tsgraph will auto-update; run codegraph sync 的降级提示),等两三秒让增量同步完成。
  2. 手动同步。若等待后仍缺失,手动执行 codegraph sync 强制增量同步。
  3. 确认文件可被索引
    • 文件语言是否在 受支持语言列表 中;
    • 文件是否位于被 .gitignore 忽略或默认排除的目录中(例如 node_modulesdist)——这类目录本来就不进索引,其中的符号自然"缺失"。

与自动同步相关的补充细节(帮助判断"到底是没同步,还是同步被禁用了"):

  • 服务器会周期性做陈旧度检查。如果工具响应开头出现 ⚠️ Some files referenced below were edited since the last index sync… 横幅,说明只是少量文件待重索引——横幅中列出的文件需直接 Read 获取最新内容,其余文件仍可信任图谱(该横幅语义定义在 src/mcp/server-instructions.ts)。
  • 另一种更罕见的横幅 ⚠️ CodeGraph auto-sync is DISABLED — live file watching stopped 表示整个索引已冻结(通常是 OS 文件监听限制耗尽),此时应对所有可能变更的内容直接读文件确认,并手动 codegraph sync(见 src/mcp/tools.tssrc/sync/watcher.tsOS watch/file limit exhausted; auto-sync disabled)。
  • 监听降级是有预算的:src/sync/watcher.ts 的注释说明,短暂的写锁竞争(重试预算内)会等待,只有确定性失败(如 tree-sitter 解析错误)或竞争耗尽重试预算时才会禁用自动同步并降级。

问题六:Windows 与 WSL 共享同一个检出(checkout)

核心结论:不要让两侧指向同一个 .codegraph/ 原因有二(官方文档与源码注释完全一致):

  1. 后台服务器锁与 SQLite 索引都"绑定"于写入它们的操作系统.codegraph/daemon.pid 记录的是平台相关的 pid 与 socket 路径——Windows 上是命名管道,WSL 上是 Unix socket,两者互不兼容;
  2. SQLite 文件锁跨 WSL2 ↔ Windows 文件系统边界不可靠。两个 daemon 共享一个索引会导致损坏。

正确做法:给其中一侧设置 CODEGRAPH_DIR 指向独立目录名,让同一棵项目树里各自持有独立索引。例如 Windows 侧设置 CODEGRAPH_DIR=.codegraph-win,WSL 侧保持默认 .codegraph

该机制的实现细节值得展开,全部在 src/directory.ts

export function codeGraphDirName(): string {
  const raw = process.env.CODEGRAPH_DIR?.trim();
  if (!raw) return DEFAULT_CODEGRAPH_DIR;          // 默认 '.codegraph'
  const invalid =
    raw === '.' || raw.includes('..') ||
    raw.includes('/') || raw.includes('\\') ||
    path.isAbsolute(raw);
  if (invalid) { /* 警告一次并回退默认值 */ return DEFAULT_CODEGRAPH_DIR; }
  return raw;
}

要点:

  • 校验规则CODEGRAPH_DIR 必须是单个纯目录名——不能为空、不能含路径分隔符、不能是 ./.. 或绝对路径。非法值会被忽略并回退到默认 .codegraph,同时向 stderr 警告一次(不能走 stdout,因为那是 MCP 协议通道)。这保证索引绝不会写到项目目录之外。
  • 索引目录互不干扰isCodeGraphDataDir 会把默认 .codegraph、当前生效的 CODEGRAPH_DIR 覆盖值以及任何 .codegraph-* 兄弟目录都识别为"CodeGraph 数据目录";文件监听与索引过程会跳过所有这些目录。因此 Windows 的 .codegraph-win 永远不会出现在 WSL 侧的监听/索引目标里,反之亦然——这正是文档所说"the two never trip over each other"的源码保证。
  • 慢速文件系统提示:如果你的 WSL 项目位于 /mnt 下(对 WSL 而言是 Windows 文件系统,慢且锁行为不可靠),codegraph index 提供 --no-watch 选项关闭文件监听(帮助文本明确写道"useful on slow filesystems like WSL2 /mnt drives",见 src/bin/codegraph.ts);但更彻底的方案仍是把项目放到 WSL 本地文件系统,同时解决慢与锁两类问题。

附:快速自检清单

把六个问题串成一条排查流水线,遇到异常时可以按序执行:

步骤 命令/动作 期望结果
1 codegraph status 显示 Project:Index Statistics:Not initialized 则先 codegraph init
2 查看 Journal: 显示绿色的 wal;否则见问题三(旧安装 / 非本地文件系统)
3 查看 DB Size / WAL Size WAL 正常时应小于 DB;若 WAL Size 大于数据库并被黄色标出,说明有被杀会话遗留(打开时会自动回收,见 WAL_HEAL_THRESHOLD_BYTES 的自动修复机制,可用 CODEGRAPH_WAL_HEAL_MB 调整阈值,默认 64 MB)
4 检查 codegraph status 中的警告行 indexing/partial/failed 状态提示重跑 codegraph indexpendingRefs 非零提示运行 codegraph sync 补全中断的解析(对应 src/bin/codegraph.ts
5 确认 MCP 配置路径 路径错误则重跑 codegraph install 重写配置
6 Windows/WSL 双环境 为一侧设置 CODEGRAPH_DIR=.codegraph-win,两侧各持独立索引

以上所有判定逻辑(初始化条件、journal 模式展示、状态机警告、目录名解析)都直接对应 src/directory.tssrc/bin/codegraph.tssrc/db/index.ts 中的实现,排查遇到本文未覆盖的新症状时,可以按错误信息中的关键词在这些文件中检索对应分支,快速定位触发条件。

登录后查看全文
热门项目推荐
相关项目推荐