nodejs/node · error · RuntimeError

Failed to find //buildtools directory for checkdeps

Error message

Failed to find //buildtools directory for checkdeps

What it means

V8's PRESUBMIT.py wires up the checkdeps include-rule linter by locating the //buildtools/checkdeps package. It looks for a 'buildtools' dir in the current presubmit path, then one level up; if neither exists it raises RuntimeError because checkdeps can't be imported and dependency rules can't be evaluated.

Source

Thrown at deps/v8/PRESUBMIT.py:179

  return results



def _CheckUnwantedDependencies(input_api, output_api):
  """Runs checkdeps on #include statements added in this
  change. Breaking - rules is an error, breaking ! rules is a
  warning.
  """
  # We need to wait until we have an input_api object and use this
  # roundabout construct to import checkdeps because this file is
  # eval-ed and thus doesn't have __file__.
  original_sys_path = sys.path
  try:
    root = input_api.PresubmitLocalPath()
    if not os.path.exists(os.path.join(root, 'buildtools')):
      root = os.path.dirname(root)
      if not os.path.exists(os.path.join(root, 'buildtools')):
        raise RuntimeError(
            "Failed to find //buildtools directory for checkdeps")
    sys.path = sys.path + [
        input_api.os_path.join(root, 'buildtools', 'checkdeps')
    ]
    import checkdeps
    from cpp_checker import CppChecker
    from rules import Rule
  finally:
    # Restore sys.path to what it was before.
    sys.path = original_sys_path

  def _FilesImpactedByDepsChange(files):
    all_files = [f.AbsoluteLocalPath() for f in files]
    deps_files = [p for p in all_files if IsDepsFile(p)]
    impacted_files = union([_CollectImpactedFiles(path) for path in deps_files])
    impacted_file_objs = [ImpactedFile(path) for path in impacted_files]
    return impacted_file_objs

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Run `gclient sync` (or `gclient sync --deps=v8`) so buildtools is fetched next to v8.
  2. Run the presubmit from the repo root that actually contains buildtools, not a subdirectory.
  3. If you vendored v8 manually, also vendor the matching buildtools directory at the expected level.

Example fix

# before: standalone v8 checkout without DEPS
python deps/v8/PRESUBMIT.py
# after
gclient sync
python deps/v8/PRESUBMIT.py
Defensive patterns

Strategy: validation

Validate before calling

import os
root = os.getcwd()
assert os.path.isdir(os.path.join(root,'buildtools')) or os.path.isdir(os.path.join(os.path.dirname(root),'buildtools')), 'run gclient sync to fetch buildtools before presubmit'

Prevention

When it happens

Trigger: Raised in _CheckNoApiUsage/_CheckDeps when `os.path.exists(input_api.PresubmitLocalPath()/buildtools)` and `os.path.exists(dirname(PresubmitLocalPath())/buildtools)` are both false — i.e. the presubmit is run from a checkout that doesn't contain buildtools.

Common situations: Running V8's presubmit on a standalone V8 checkout fetched without its DEPS (gclient sync skipped); running PRESUBMIT.py from inside Node's deps/v8 where buildtools lives at the Node root, two levels up, not one; vendoring V8 into another repo without bringing buildtools along.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/d4b743d4569abdeb. Report an issue: GitHub.