fix(cli): hard-exit on Node 25.x instead of soft warning + cryptic crash#149
Merged
Conversation
The Node 25.x V8 turboshaft WASM JIT Zone allocator bug (#81) reliably crashes CodeGraph mid-indexing with `Fatal process out of memory: Zone` when tree-sitter grammars get JIT-compiled. We already had: - `engines: "node": ">=18.0.0 <25.0.0"` in package.json - Lazy grammar loading (#61) - A startup `console.warn` when Node 25+ is detected But the recurring duplicates (#54, #81, #140, plus comments from multiple unique users) show those defenses aren't enough: - npm `engines` is a soft warning by default, so `npm install -g` doesn't block. - The startup `console.warn` is a single yellow line that scrolls off-screen before the OOM 30 seconds later, so users connect the crash to "CodeGraph is broken" rather than "I'm on the wrong Node version" and file a fresh issue. This patch turns the soft warning into a hard exit. On Node 25+ we print a bordered banner that names the V8 root cause, embeds the detected version, gives Node 22 LTS install commands (nvm + Homebrew), and links to #81 — then exit(1) BEFORE any tree-sitter import triggers WASM JIT. The previous behaviour is preserved behind `CODEGRAPH_ALLOW_UNSAFE_NODE=1` for anyone who patched V8 themselves or wants to test a future Node 25 fix. The banner builder is extracted to `src/bin/node-version-check.ts` so the test can import it without triggering CLI bootstrap. Five unit tests pin the version interpolation, root-cause explanation, recovery commands (nvm + brew), override env var, and #81 link — these are load-bearing and shouldn't get edited away silently. Suite: 509 → 514, all passing. Verified both paths manually by flipping the threshold to 22 in dist and running on Node 22.20.0: without the env var the CLI prints the banner and exits 1; with `CODEGRAPH_ALLOW_UNSAFE_NODE=1` it prints the banner and continues. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
<25.0.0, lazy grammars fix: Lazy grammar loading to prevent V8 WASM OOM on large codebases #61, startupconsole.warn) aren't enough — npmenginesis a soft warning by default, and the runtime warning is a single yellow line that scrolls off-screen before the OOM crash 30 seconds later. Users connect the crash to "CodeGraph is broken" rather than "I'm on Node 25" and file a fresh issue.exit(1)BEFORE any tree-sitter import triggers WASM JIT. Override available viaCODEGRAPH_ALLOW_UNSAFE_NODE=1.What changed
console.warnyellow line, init continues, OOM crash mid-indexingexit(1)before any WASM workFatal process out of memory: ZonemeansCODEGRAPH_ALLOW_UNSAFE_NODE=1restores the warn-and-continue behaviorBanner content (verified by 5 unit tests so future edits can't silently strip the recovery commands or override hint):
The banner builder lives in a new
src/bin/node-version-check.tsso it's importable from tests without dragging in CLI bootstrap side-effects.Test plan
npm test— 514/514 passing (was 509; +5 new tests pin the banner content)dist/, rannode dist/bin/codegraph.js statuson Node 22.20.0 → banner printed, exit code 1, no further work happenedCODEGRAPH_ALLOW_UNSAFE_NODE=1→ banner printed, CLI continued and ran the status command normally🤖 Generated with Claude Code