nodejs/node · error · RuntimeError
Unable to find a valid ninja output directory.
Error message
Unable to find a valid ninja output directory.
What it means
Raised by GetNinjaOutputDirectory in deps/v8/tools/vim/ninja_output.py when generate_paths() yields no candidate build directories, so max(..., key=...) raises ValueError, which is caught and re-raised as this RuntimeError. It is used by V8's Vim syntastic/ale integration to locate the build output for clangd/compilation.
Source
Thrown at deps/v8/tools/vim/ninja_output.py:65
path = os.path.join(out_path, config)
if os.path.exists(os.path.join(path, 'build.ninja')):
yield path
def approx_directory_mtime(path):
# This is a heuristic; don't recurse into subdirectories.
paths = [path] + [os.path.join(path, f) for f in os.listdir(path)]
return max(filter(None, [safe_mtime(p) for p in paths]))
def safe_mtime(path):
try:
return os.path.getmtime(path)
except OSError:
return None
try:
return max(generate_paths(), key=approx_directory_mtime)
except ValueError:
raise RuntimeError('Unable to find a valid ninja output directory.')
if __name__ == '__main__':
if len(sys.argv) != 2:
raise RuntimeError('Expected a single path argument.')
print(GetNinjaOutputDirectory(sys.argv[1]))
View on GitHub (pinned to 1b2de5e052)
Solutions
- Build first: run gn gen out/Release (or out/build) then ninja -C out/Release so an output directory exists.
- Confirm the path passed to GetNinjaOutputDirectory is the V8 source root containing the out/ tree.
- If using a custom output dir, create a symlink or adjust the heuristics in ninja_output.py to include it.
Example fix
# before (no build output yet) :make # after gn gen out/Release && ninja -C out/Release # then re-run the Vim command
Defensive patterns
Strategy: validation
Validate before calling
import os
def has_build_output(project_root: str) -> bool:
return any(os.path.isdir(os.path.join(project_root, d)) for d in ('out','build')) and \
any(os.path.isdir(os.path.join(project_root, 'out', c)) for c in os.listdir(os.path.join(project_root, 'out'))) if os.path.isdir(os.path.join(project_root,'out')) else False Type guard
null
Try / catch
from tools.vim.ninja_output import GetNinjaOutputDirectory
try:
out = GetNinjaOutputDirectory(project_root)
except RuntimeError:
out = None
print('Build the project first: gn gen out/Release && ninja -C out/Release') Prevention
- Run gn gen + ninja before invoking the Vim integration.
- Point the script at the source root containing out/.
- Symlink non-standard output dirs into out/ for the heuristics to find them.
When it happens
Trigger: Calling GetNinjaOutputDirectory(path) where no out/<config> or build output directory exists under the given project path; all generated candidate paths are empty so approx_directory_mtime has nothing to compare.
Common situations: Using the V8 Vim integration before running gn gen / ninja; pointing the script at a fresh checkout with no build artifacts; the build output lives in a non-standard location the heuristics don't search.
Related errors
- did not generate any of %s
- Expected a single path argument.
- --enable-v8windbg is incompatible with --without-bundled-v8.
- --v8-enable-hugepage is supported only on linux.
- Only one of the --v8-enable-object-print or --v8-disable-obj
AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13).
Data as JSON: /api/errors/ee7a9f876d2e33bd.
Report an issue: GitHub.