Skip to content

v1.1.3 Codex MCP on WSL /mnt can open same repo via upper/lowercase paths, corrupting .codegraph despite CODEGRAPH_NO_DAEMON #1057

Description

@yjtdkj

Summary

On @colbymchenry/codegraph@1.1.3, Codex MCP still becomes unstable on WSL2 /mnt/d even with the recommended workaround from #974:

[mcp_servers.codegraph]
command = "env"
args = ["CODEGRAPH_NO_DAEMON=1", "codegraph", "serve", "--mcp", "--no-watch"]

The new distinguishing signal is that a single Codex parent process spawned two CodeGraph MCP server processes for the same physical repository with different path casing:

Codex parent:
3608352 .../bin/codex
parent cwd=/mnt/d/02_SoftwareCodes/RCSS.Studio/Tekla/TeklaDrawingHelper_TeklaInternal

CodeGraph MCP children of the same parent:
3608757 cwd=/mnt/d/02_SoftwareCodes/RCSS.Studio/Tekla/TeklaDrawingHelper_TeklaInternal
3609744 cwd=/mnt/d/02_softwarecodes/rcss.studio/tekla/tekladrawinghelper_teklainternal

Both paths point to the same .codegraph/codegraph.db inode on DrvFs:

upper=70:6192449487701361 /mnt/d/02_SoftwareCodes/RCSS.Studio/Tekla/TeklaDrawingHelper_TeklaInternal/.codegraph/codegraph.db
lower=70:6192449487701361 /mnt/d/02_softwarecodes/rcss.studio/tekla/tekladrawinghelper_teklainternal/.codegraph/codegraph.db

After this, CLI codegraph status reported:

Failed to get status: database disk image is malformed

Killing the repo-matching CodeGraph MCP processes made CLI status/sync recover, but the Codex MCP tool call then failed with:

Error: tool call error: tool call failed for `codegraph/codegraph_explore`
Caused by:
    Transport closed

Environment

  • CodeGraph: 1.1.3
  • Node: v22.19.0
  • Client: OpenAI Codex CLI
  • OS: WSL2 Ubuntu on Windows, project on /mnt/d DrvFs
  • Project path used by shell / parent process:
    /mnt/d/02_SoftwareCodes/RCSS.Studio/Tekla/TeklaDrawingHelper_TeklaInternal
  • MCP config:
[mcp_servers.codegraph]
command = "env"
args = ["CODEGRAPH_NO_DAEMON=1", "codegraph", "serve", "--mcp", "--no-watch"]

Observed process state

pwd and pwd -P from the active shell both showed the uppercase canonical-looking path:

/mnt/d/02_SoftwareCodes/RCSS.Studio/Tekla/TeklaDrawingHelper_TeklaInternal
/mnt/d/02_SoftwareCodes/RCSS.Studio/Tekla/TeklaDrawingHelper_TeklaInternal

The Codex parent process also had the uppercase cwd:

3608352 3608345 Mon Jun 29 15:39:36 2026 .../bin/codex
parent cwd=/mnt/d/02_SoftwareCodes/RCSS.Studio/Tekla/TeklaDrawingHelper_TeklaInternal

But the same parent spawned two CodeGraph MCP server processes:

PID 3608757
ppid=3608352
cwd=/mnt/d/02_SoftwareCodes/RCSS.Studio/Tekla/TeklaDrawingHelper_TeklaInternal
env=CODEGRAPH_NO_DAEMON=1
cmdline=node .../bin/codegraph serve --mcp --no-watch

PID 3609744
ppid=3608352
cwd=/mnt/d/02_softwarecodes/rcss.studio/tekla/tekladrawinghelper_teklainternal
env=CODEGRAPH_NO_DAEMON=1
cmdline=node .../bin/codegraph serve --mcp --no-watch

The Codex MCP tool call also carried the lower-case project path:

codegraph.codegraph_explore({
  "projectPath": "/mnt/d/02_softwarecodes/rcss.studio/tekla/tekladrawinghelper_teklainternal",
  "query": "RunCurrentVersionSwitch CurrentVersionSwitchService ExecuteBatch ValidateBatchPreconditions RecordBatchNotExecuted DrawingTransferManagerForm CanExecuteBatchVersionSwitch DrawingTransferPlanRecord IsExecutableRecord",
  "maxFiles": 5
})

Daemon-related observation despite CODEGRAPH_NO_DAEMON=1

Even with CODEGRAPH_NO_DAEMON=1 in the MCP server environment, .codegraph/daemon.pid contained a relocated daemon:

{
  "pid": 3607983,
  "version": "1.1.3",
  "socketPath": "/tmp/codegraph-befc5052950cc73f.sock",
  "startedAt": 1782718772179
}

Process:

PID 3607983
cwd=/mnt/d/02_SoftwareCodes/RCSS.Studio/Tekla/TeklaDrawingHelper_TeklaInternal
env=CODEGRAPH_DAEMON_INTERNAL=1
cmdline=.../codegraph.js serve --mcp --path /mnt/d/02_SoftwareCodes/RCSS.Studio/Tekla/TeklaDrawingHelper_TeklaInternal

.codegraph/daemon.log included:

[CodeGraph daemon] Socket /mnt/d/02_SoftwareCodes/RCSS.Studio/Tekla/TeklaDrawingHelper_TeklaInternal/.codegraph/daemon.sock unusable (ENOTSUP); relocating to /tmp/codegraph-befc5052950cc73f.sock.
[CodeGraph daemon] Listening on /tmp/codegraph-befc5052950cc73f.sock (pid 3607983, v1.1.3). Idle timeout 300000ms.
[CodeGraph MCP] File watcher disabled — project is on a WSL2 /mnt/ drive, where recursive fs.watch is too slow to be reliable. The graph will not auto-update; run `codegraph sync` (or install the git sync hooks via `codegraph init`) to refresh.

This may be expected under some path, but it was surprising because the user-facing MCP process had CODEGRAPH_NO_DAEMON=1.

Symptoms

  1. codegraph sync was run.
  2. codegraph status then failed:
Failed to get status: database disk image is malformed
  1. Multiple CodeGraph MCP processes existed, including two for the same physical repo via upper/lower casing.
  2. After killing repo-matching processes, CLI status recovered and sync completed.
  3. The subsequent Codex MCP call failed:
Error: tool call error: tool call failed for `codegraph/codegraph_explore`
Caused by:
    Transport closed

Why this seems distinct from #974

#974 was on v1.1.0 and the recommended workaround was CODEGRAPH_NO_DAEMON=1 to skip the shared daemon on WSL2 /mnt.

In this case:

  • CodeGraph is 1.1.3.
  • The MCP server process has CODEGRAPH_NO_DAEMON=1.
  • The MCP server also has --no-watch.
  • The same Codex parent process spawns two CodeGraph MCP children for the same physical repo with different path casing.
  • The same SQLite database inode is shared by those two path spellings.
  • A relocated internal daemon still appears in .codegraph/daemon.pid.
  • The index can become malformed, then CLI recovers after killing repo-matching MCP processes, while MCP still returns Transport closed.

Expected behavior

On WSL2 /mnt / DrvFs, CodeGraph should either:

  • canonicalize/case-fold project roots that point to the same physical directory before deciding project identity and .codegraph ownership, or
  • lock the SQLite database robustly across equivalent path spellings, or
  • fail fast with an actionable error when the same physical .codegraph directory is opened through multiple path spellings.

It should not allow two MCP processes from the same client parent to treat upper/lowercase spellings of the same DrvFs path as separate project roots while writing the same SQLite database.

Questions

  1. Is CODEGRAPH_NO_DAEMON=1 expected to fully prevent creation/use of a shared daemon in v1.1.3, or can a relocated CODEGRAPH_DAEMON_INTERNAL=1 process still appear?
  2. Does CodeGraph currently canonicalize WSL DrvFs paths by physical identity, or only by path string/realpath?
  3. Would you prefer this be fixed in CodeGraph project-root identity handling, or should MCP clients like Codex avoid sending projectPath values that differ in casing from the server process cwd?

I can provide additional command transcripts if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions