Symptom
On a developer machine running Node.js 25 or later, npm test against main reports:
Test Files 4 failed | 44 passed (48)
Tests 13 failed | 1019 passed | 2 skipped (1034)
All 13 failures are in subprocess-based MCP integration tests:
| File |
Failing tests |
__tests__/mcp-daemon.test.ts |
7 |
__tests__/mcp-initialize.test.ts |
2 |
__tests__/mcp-ppid-watchdog.test.ts |
1 |
__tests__/mcp-roots.test.ts |
3 |
The failure mode is always the same: every assertion that waits for an MCP message from the spawned child times out with Timed out. Messages so far: []. The PPID-watchdog test instead fails with expected false to be true (the kill(pid, 0) probe never sees the child exit because the child died on startup, not on SIGKILL).
Root cause
src/bin/codegraph.ts:65–71 hard-blocks the CLI when nodeMajor >= 25:
if (nodeMajor >= 25) {
process.stderr.write(buildNode25BlockBanner(nodeVersion) + '\n');
if (!process.env.CODEGRAPH_ALLOW_UNSAFE_NODE) {
process.exit(1);
}
}
Each affected test spawns node dist/bin/codegraph.js serve --mcp … with the test process's own Node binary (process.execPath). On Node ≥25, that child writes the unsupported-version banner and exits before the test sends initialize, so every subsequent waitForMessage times out.
The block exists for good reason (Node 25's V8 turboshaft WASM JIT Zone allocator bug, issue #81), but the test scenarios — short-lived servers, no production indexing — won't hit the OOM the block protects against. The CLI itself should still enforce the block for end users.
Confirmed fix
Setting CODEGRAPH_ALLOW_UNSAFE_NODE=1 in the environment vitest inherits makes all 13 tests pass on Node 26.x:
$ CODEGRAPH_ALLOW_UNSAFE_NODE=1 npx vitest run __tests__/mcp-roots.test.ts
Test Files 1 passed (1)
Tests 3 passed (3)
$ CODEGRAPH_ALLOW_UNSAFE_NODE=1 npx vitest run __tests__/mcp-ppid-watchdog.test.ts
Test Files 1 passed (1)
Tests 1 passed (1)
Since each spawning test already builds its child env via { ...process.env, ... } (or inherits process.env when no env is passed), setting the variable once in vitest.config.ts propagates it to every spawned subprocess without modifying any individual test file.
Impact
- CI on Node 22/23 is unaffected (the block only fires on ≥25).
- New contributors on a recent macOS/Linux box (Node 25+ shipped via Homebrew / nvm latest) currently get a noisy
npm test baseline and have to discover the env-var workaround to verify their changes. The note in CLAUDE.md about pre-existing Windows failures doesn't mention this macOS/Linux case, so the failures look unrelated to the underlying Node version.
Proposed fix
Set CODEGRAPH_ALLOW_UNSAFE_NODE=1 via vitest.config.ts's test.env so it propagates into every spawned subprocess and the suite is green on any supported (or newer) Node. PR to follow.
Symptom
On a developer machine running Node.js 25 or later,
npm testagainstmainreports:All 13 failures are in subprocess-based MCP integration tests:
__tests__/mcp-daemon.test.ts__tests__/mcp-initialize.test.ts__tests__/mcp-ppid-watchdog.test.ts__tests__/mcp-roots.test.tsThe failure mode is always the same: every assertion that waits for an MCP message from the spawned child times out with
Timed out. Messages so far: []. The PPID-watchdog test instead fails withexpected false to be true(thekill(pid, 0)probe never sees the child exit because the child died on startup, not on SIGKILL).Root cause
src/bin/codegraph.ts:65–71hard-blocks the CLI whennodeMajor >= 25:Each affected test spawns
node dist/bin/codegraph.js serve --mcp …with the test process's own Node binary (process.execPath). On Node ≥25, that child writes the unsupported-version banner and exits before the test sendsinitialize, so every subsequentwaitForMessagetimes out.The block exists for good reason (Node 25's V8 turboshaft WASM JIT Zone allocator bug, issue #81), but the test scenarios — short-lived servers, no production indexing — won't hit the OOM the block protects against. The CLI itself should still enforce the block for end users.
Confirmed fix
Setting
CODEGRAPH_ALLOW_UNSAFE_NODE=1in the environment vitest inherits makes all 13 tests pass on Node 26.x:Since each spawning test already builds its child env via
{ ...process.env, ... }(or inherits process.env when noenvis passed), setting the variable once invitest.config.tspropagates it to every spawned subprocess without modifying any individual test file.Impact
npm testbaseline and have to discover the env-var workaround to verify their changes. The note inCLAUDE.mdabout pre-existing Windows failures doesn't mention this macOS/Linux case, so the failures look unrelated to the underlying Node version.Proposed fix
Set
CODEGRAPH_ALLOW_UNSAFE_NODE=1viavitest.config.ts'stest.envso it propagates into every spawned subprocess and the suite is green on any supported (or newer) Node. PR to follow.